actualbudget/actual · error

invalid-prefs

invalid-prefs

Error message

invalid-prefs

What it means

HTTP 400 from POST /server-prefs with `reason:'invalid-prefs'`. After the admin check, the endpoint destructures `prefs` from the body and requires it to be a truthy object; otherwise it rejects the request without calling `setServerPrefs`. This is a server-side schema validation for the prefs payload.

Source

Thrown at packages/sync-server/src/app-account.js:179

});

app.post('/server-prefs', (req, res) => {
  const session = validateSession(req, res);
  if (!session) return;

  if (!isAdmin(session.user_id)) {
    res.status(403).send({
      status: 'error',
      reason: 'forbidden',
      details: 'permission-not-found',
    });
    return;
  }

  const { prefs } = req.body || {};

  if (!prefs || typeof prefs !== 'object') {
    res.status(400).send({ status: 'error', reason: 'invalid-prefs' });
    return;
  }

  setServerPrefs(prefs);

  res.send({ status: 'ok', data: {} });
});

app.get('/validate', (req, res) => {
  const session = validateSession(req, res);
  if (session) {
    const user = getUserInfo(session.user_id);
    if (!user) {
      res.status(400).send({ status: 'error', reason: 'User not found' });
      return;
    }

    res.send({

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Wrap the settings in a `prefs` key: `{"prefs": {"key": "value"}}` with Content-Type application/json.
  2. Validate on the client that `typeof prefs === 'object' && prefs !== null` before calling the endpoint.
  3. If req.body is empty, fix the request encoding/Content-Type so express.json() parses it.

Example fix

// before
await api.post('/server-prefs', { 'cloudFileId': 'x' });
// after
await api.post('/server-prefs', { prefs: { 'cloudFileId': 'x' } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidPrefsPayload(body) {
  return body != null && typeof body.prefs === 'object' && body.prefs !== null && !Array.isArray(body.prefs);
}
if (!isValidPrefsPayload({ prefs })) throw new Error('POST /server-prefs requires body { prefs: object }');

Type guard

function isPrefsBody(b) {
  return typeof b === 'object' && b !== null && 'prefs' in b && typeof b.prefs === 'object';
}

Try / catch

try {
  await post('/server-prefs', { prefs }, jsonHeaders);
} catch (e) {
  if (e.response?.data?.reason === 'invalid-prefs') throw new PayloadError('prefs must be a non-null object');
  throw e;
}

Prevention

When it happens

Trigger: POST /server-prefs with a body missing the `prefs` key, `prefs: null`, `prefs` as a string/number/array-like, or a body that fails to parse so `req.body` is undefined (`req.body || {}` yields no prefs).

Common situations: Client sends `{}` instead of `{prefs:{...}}`; sends the prefs object at the top level; Content-Type not application/json so req.body is empty; automation sending form-encoded data.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/add1544ea833ff23. Report an issue: GitHub.