Errors
This page explains how errors work in rix/auth.
The examples use the public Rix facade:
#include <rix.hpp>and Auth error helpers through:
rix.auth.errorRix Auth uses explicit errors for normal authentication failures.
It does not use exceptions for expected authentication cases such as invalid credentials, invalid passwords, duplicate users, expired sessions, or revoked sessions.
Basic idea
Operations that return data use result objects:
auto login = auth.login({
"ada@example.com",
"wrong-password"
});Check the result:
if (login.failed())
{
const auto &error = login.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message()
);
return 1;
}Operations that only return success or failure use status objects:
auto status = auth.logout(session_id);
if (status.failed())
{
const auto &error = status.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message()
);
return 1;
}Result and status types
Auth uses two main patterns:
AuthResult<T>
AuthStatusAuthResult<T> is used when an operation returns data.
Examples:
AuthResult<User>
AuthResult<LoginResult>
AuthResult<Session>
AuthResult<Token>
AuthResult<std::string>AuthStatus is used when an operation only returns success or failure.
Examples:
logout(...)
logout_user(...)
store.update(...)
store.remove_by_id(...)
store.revoke_by_id(...)Complete example
Create a file:
mkdir -p ~/rix-auth-errors
cd ~/rix-auth-errors
touch errors.cppAdd:
#include <rix.hpp>
int main()
{
rix.debug.print("== rix/auth errors ==");
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"ada@example.com",
"correct-password"
});
if (registered.failed())
{
const auto &error = registered.error();
rix.debug.eprint(
"registration error:",
rix.auth.error.to_string(error),
error.message()
);
return 1;
}
auto duplicate = auth.register_user({
"ada@example.com",
"correct-password"
});
if (duplicate.failed())
{
const auto &error = duplicate.error();
rix.debug.print("----------------------------------------");
rix.debug.print("duplicate registration failed as expected");
rix.debug.print("code:", rix.auth.error.to_string(error));
rix.debug.print("message:", error.message());
}
auto login = auth.login({
"ada@example.com",
"wrong-password"
});
if (login.failed())
{
const auto &error = login.error();
rix.debug.print("----------------------------------------");
rix.debug.print("login failed as expected");
rix.debug.print("code:", rix.auth.error.to_string(error));
rix.debug.print("message:", error.message());
}
auto session = auth.authenticate_session("missing-session");
if (session.failed())
{
const auto &error = session.error();
rix.debug.print("----------------------------------------");
rix.debug.print("session rejected as expected");
rix.debug.print("code:", rix.auth.error.to_string(error));
rix.debug.print("message:", error.message());
}
return 0;
}Run it:
vix run errors.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run errors.cppExpected output
The output should look like this:
== rix/auth errors ==
----------------------------------------
duplicate registration failed as expected
code: UserAlreadyExists
message: User already exists.
----------------------------------------
login failed as expected
code: InvalidCredentials
message: Invalid credentials.
----------------------------------------
session rejected as expected
code: InvalidSession
message: Session not found.The exact messages can evolve, but the error pattern stays the same.
Error object
An Auth error contains:
code
messageThe code is stable and useful for programmatic decisions.
The message is human-readable and useful for diagnostics.
Example:
const auto &error = login.error();
auto code = error.code();
auto message = error.message();Convert the code to a stable string:
rix.auth.error.to_string(error)or:
rix.auth.error.to_string(error.code())Check success or failure
An error can be checked directly:
bool ok = rix.auth.error.ok(error);
bool failed = rix.auth.error.failed(error);The error object also exposes:
error.ok()
error.has_error()For normal Auth operations, prefer checking the result or status:
if (login.failed())
{
const auto &error = login.error();
}Check a specific error code
Use:
rix.auth.error.is(error, rixlib::auth::AuthErrorCode::InvalidCredentials)Example:
if (login.failed())
{
const auto &error = login.error();
if (rix.auth.error.is(
error,
rixlib::auth::AuthErrorCode::InvalidCredentials
))
{
rix.debug.eprint("Invalid email or password.");
}
}Use this when the application needs different behavior for different errors.
Create an error
You can create an error manually:
auto error = rix.auth.error.make(
rixlib::auth::AuthErrorCode::InvalidInput,
"Invalid input."
);Create a success error value:
auto ok = rix.auth.error.none();Most application code receives errors from Auth operations instead of creating them manually.
Manual creation is useful for tests, custom stores, and integrations.
Error codes
rix/auth exposes stable error codes through:
rixlib::auth::AuthErrorCodeCurrent codes:
None
InvalidInput
InvalidState
InvalidEmail
InvalidPassword
UserNotFound
UserAlreadyExists
InvalidCredentials
EmailVerificationRequired
UserDisabled
InvalidSession
SessionExpired
SessionRevoked
InvalidToken
TokenExpired
TokenRevoked
StoreError
CryptoError
ValidationError
ConfigurationError
UnknownCommon registration errors
Registration can fail with:
InvalidInput
InvalidEmail
InvalidPassword
UserAlreadyExists
StoreError
CryptoError
ValidationError
ConfigurationErrorExample:
auto registered = auth.register_user({
"not-an-email",
"short"
});
if (registered.failed())
{
const auto &error = registered.error();
rix.debug.eprint(
"registration failed:",
rix.auth.error.to_string(error),
error.message()
);
}Common login errors
Login can fail with:
InvalidEmail
InvalidPassword
UserNotFound
InvalidCredentials
EmailVerificationRequired
UserDisabled
StoreErrorFor public application responses, avoid revealing whether the email exists.
Use a generic public message:
Invalid email or password.Keep the stable error code for logs and diagnostics.
Common session errors
Session operations can fail with:
InvalidSession
SessionExpired
SessionRevoked
StoreError
InvalidInputExample:
auto session = auth.authenticate_session(session_id);
if (session.failed())
{
const auto &error = session.error();
if (rix.auth.error.is(
error,
rixlib::auth::AuthErrorCode::SessionExpired))
{
rix.debug.eprint("session expired");
}
}Common token errors
Token operations can fail with:
InvalidInput
InvalidToken
TokenExpired
TokenRevoked
StoreError
CryptoError
UnknownExample:
auto token = auth.issue_token(user_id);
if (token.failed())
{
const auto &error = token.error();
rix.debug.eprint(
"token error:",
rix.auth.error.to_string(error),
error.message()
);
}Common configuration errors
Configuration validation can fail with:
ConfigurationErrorExample:
auto config = rix.auth.config.development();
config.set_min_password_length(20);
config.set_max_password_length(8);
auto status = rix.auth.config.validate(config);
if (status.failed())
{
const auto &error = status.error();
rix.debug.eprint(
"config error:",
rix.auth.error.to_string(error),
error.message()
);
}Common store errors
Store operations can fail with:
StoreError
InvalidInput
InvalidState
UserNotFound
UserAlreadyExists
InvalidSessionStoreError usually means the storage backend failed.
For memory stores, this is uncommon.
For database stores, this can happen when the database operation fails.
Use the message for diagnostics.
Result pattern
Operations that return values must be checked before .value() is used.
Correct:
auto login = auth.login({
"ada@example.com",
"correct-password"
});
if (login.failed())
{
const auto &error = login.error();
return 1;
}
auto user = login.value().user;Wrong:
auto login = auth.login({
"ada@example.com",
"correct-password"
});
auto user = login.value().user;The wrong version assumes success before checking the result.
Status pattern
Status-only operations are checked in the same way:
auto status = auth.logout(session_id);
if (status.failed())
{
const auto &error = status.error();
return 1;
}You can also use ok():
if (status.ok())
{
rix.debug.print("logout successful");
}Boolean conversion
Results and statuses can be used in boolean contexts:
if (login)
{
rix.debug.print("login ok");
}and:
if (!status)
{
rix.debug.eprint("operation failed");
}For documentation and clarity, prefer:
login.failed()
login.ok()
status.failed()
status.ok()Public API responses
In an HTTP application, do not expose every internal detail.
For login, prefer a generic response:
Invalid email or password.even if the internal error is:
UserNotFound
InvalidCredentials
InvalidPasswordFor registration, it is usually acceptable to tell the user that the email is already used, depending on your product policy.
For sessions, expired or revoked sessions should usually ask the user to login again.
Debug output
For examples and local development:
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message()
);For real application logging, prefer the Vix logging system.
Avoid logging secrets.
Security notes
Never log:
plain-text passwords
password hashes
session ids
raw token valuesBe careful with login errors.
Avoid user enumeration by returning generic login messages.
Use stable error codes internally.
Use human-readable messages for diagnostics.
Do not send sensitive internal store errors directly to public clients.
Complete helper function
A small helper can keep examples clean:
#include <rix.hpp>
static void print_auth_error(
const char *label,
const rixlib::auth::AuthError &error)
{
rix.debug.eprint(
label,
rix.auth.error.to_string(error),
error.message()
);
}Usage:
auto login = auth.login({
"ada@example.com",
"wrong-password"
});
if (login.failed())
{
print_auth_error("login failed:", login.error());
return 1;
}What you should remember
Check result-returning operations:
if (result.failed())
{
const auto &error = result.error();
}Check status-returning operations:
if (status.failed())
{
const auto &error = status.error();
}Convert errors to stable strings:
rix.auth.error.to_string(error)Check specific codes:
rix.auth.error.is(
error,
rixlib::auth::AuthErrorCode::InvalidCredentials)Use stable codes for program logic.
Use messages for diagnostics.
Do not call .value() before checking ok() or failed().
Next step
Learn Auth security practices.
Next: Security