actualbudget/actual · error
${error}
Error message
${error} What it means
When POST /openid passes the admin check, it calls enableOpenID(req.body). If that function returns an error, the endpoint responds 500 with reason set to the returned error string. The message is dynamic (the raw error from enabling OpenID), so its exact text depends on what enableOpenID rejected — commonly invalid OpenID configuration discovery or issuer issues.
Source
Thrown at packages/sync-server/src/app-openid.ts:42
message: { status: 'error', reason: 'too-many-requests' },
});
export { app as handlers, openIdConfigRateLimiter };
app.post('/enable', validateSessionMiddleware, async (req, res) => {
if (!isAdmin(res.locals.user_id)) {
res.status(403).send({
status: 'error',
reason: 'forbidden',
details: 'permission-not-found',
});
return;
}
const { error } = (await enableOpenID(req.body)) || {};
if (error) {
res.status(500).send({ status: 'error', reason: error });
return;
}
res.send({ status: 'ok' });
});
app.post('/disable', validateSessionMiddleware, async (req, res) => {
if (!isAdmin(res.locals.user_id)) {
res.status(403).send({
status: 'error',
reason: 'forbidden',
details: 'permission-not-found',
});
return;
}
const { error } = (await disableOpenID(req.body)) || {};
if (error) {View on GitHub (pinned to d4334cb6e6)
Solutions
- Read the `reason` field in the 500 response — it contains the underlying enableOpenID error
- Verify the OpenID discovery URL/issuer is correct and reachable from the server
- Ensure the request body contains all required OpenID configuration fields
- Check server logs for the full stack behind the error
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check discovery URL reachability
const res = await fetch(discoveryUrl + '/.well-known/openid-configuration');
if (!res.ok) throw new Error('OpenID discovery URL unreachable before enabling'); Type guard
null
Try / catch
const { error } = await enableOpenId(body);
if (error) {
logger.error('enableOpenID failed:', error);
// fix config per the returned reason, then retry
} Prevention
- Validate the issuer/discovery URL before submitting
- Confirm the sync-server can reach the IdP (network egress, TLS)
- Send the complete expected body shape
- Read the response `reason` field — it names the exact failure
When it happens
Trigger: enableOpenID fails — e.g. the provided OpenID discovery URL is unreachable, the issuer metadata cannot be fetched/parsed, or the configuration body is invalid — causing the route to send { status:'error', reason: error } with HTTP 500.
Common situations: Entering a wrong OpenID issuer/discovery URL when configuring server authentication; OpenID provider downtime; network egress blocked from the sync-server to the IdP; malformed request body missing required fields.
Related errors
- OpenID configuration not found
- already-bootstraped
- Invalid OpenID configuration
- Error loading data into the spreadsheet.
- Unsupported summary type
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/bc54056174ced4e8.
Report an issue: GitHub.