actualbudget/actual · error
invalid-password
invalid-password
Error message
invalid-password
What it means
During OpenID bootstrapping via POST /openid/config, the submitted password is checked against the server's expected password (checkPassword). If it does not match, the endpoint responds 400 with reason 'invalid-password'. This protects the bootstrap step so only someone knowing the server password can configure OpenID.
Source
Thrown at packages/sync-server/src/app-openid.ts:76
const { error } = (await disableOpenID(req.body)) || {};
if (error) {
res.status(401).send({ status: 'error', reason: error });
return;
}
res.send({ status: 'ok' });
});
app.post('/config', openIdConfigRateLimiter, async (req, res) => {
const ownerCount = UserService.getOwnerCount();
if (ownerCount > 0) {
res.status(400).send({ status: 'error', reason: 'already-bootstraped' });
return;
}
if (!(await checkPassword(req.body.password))) {
res.status(400).send({ status: 'error', reason: 'invalid-password' });
return;
}
const auth = UserService.getOpenIDConfig();
if (!auth) {
res
.status(500)
.send({ status: 'error', reason: 'OpenID configuration not found' });
return;
}
try {
const openIdConfig = JSON.parse(auth.extra_data);
res.send({ status: 'ok', data: { openId: openIdConfig } });
} catch {
res
.status(500)View on GitHub (pinned to d4334cb6e6)
Solutions
- Send the correct server password in the request body
- Check the SERVER_PASSWORD env var / deployment config for the actual expected password
- Ensure the password field is present and not empty in the JSON body
- If the password is unknown, reset the server data to re-bootstrap from scratch
Example fix
// before
{ "openId": { ... } } // 400 invalid-password
// after
{ "password": "correct-server-password", "openId": { ... } } Defensive patterns
Strategy: validation
Validate before calling
if (typeof password !== 'string' || password.length === 0) {
throw new Error('a non-empty server password is required for bootstrap');
} Type guard
function isBootstrapBody(b: unknown): b is { password: string } {
return typeof b === 'object' && b !== null &&
typeof (b as { password?: unknown }).password === 'string' &&
(b as { password: string }).password.length > 0;
} Try / catch
if (res.status === 400 && (await res.json()).reason === 'invalid-password') {
throw new Error('server password rejected — check SERVER_PASSWORD / deployment config');
} Prevention
- Source the password from the same secret store the server uses (e.g. SERVER_PASSWORD)
- Never hardcode passwords in provisioning scripts
- Confirm the target environment before sending credentials
- Fail fast with a clear message when the password field would be empty
When it happens
Trigger: Calling POST /openid/config on an un-bootstrapped server with a `password` value that fails checkPassword (wrong or missing password in the body).
Common situations: Typos or wrong environment's password in provisioning scripts; omitting the password field entirely; password set via SERVER_PASSWORD env not matching what the script sends.
Related errors
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/4719db03458c8b94.
Report an issue: GitHub.