actualbudget/actual · warning

Invalid method parameter

Error message

Invalid method parameter

What it means

The proxy accepts an optional JSON body where `method` specifies the HTTP verb to use for the proxied request. If method is present but not a string (e.g. a number or object), the proxy returns 400 'Invalid method parameter'. Only the type is checked here; allowed verbs are validated separately.

Source

Thrown at packages/sync-server/src/app-cors-proxy.js:173

      message: 'Unable to verify allowlist',
    });
  }

  // Check if the URL is allowed
  if (!isUrlAllowed(url.href)) {
    console.warn('Blocked request to unauthorized URL:', url.href);
    return res.status(403).json({
      error: 'URL not allowed',
      message:
        'Only allowlisted plugin repositories are allowed (localhost only in development)',
    });
  }

  try {
    const { method = 'GET', headers: customHeaders = {} } = req.body || {};

    if (typeof method !== 'string') {
      return res.status(400).json({ error: 'Invalid method parameter' });
    }
    const methodNormalized = method.toUpperCase();
    if (!['GET', 'HEAD'].includes(methodNormalized)) {
      return res.status(405).json({ error: 'Method not allowed' });
    }

    const requestHeaders = {
      ...req.headers,
      ...customHeaders,
      host: url.host,
    };

    // Remove headers that shouldn't be forwarded
    delete requestHeaders['x-actual-token'];
    delete requestHeaders['content-length'];
    delete requestHeaders['cookie'];
    delete requestHeaders['cookie2'];

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Send method as a string, e.g. { method: 'GET' }.
  2. Coerce/validate the method in the calling code: typeof method === 'string' || String(method).
  3. Omit the method field entirely to use the default 'GET'.

Example fix

// before
const body = { method: statusCode }; // number
// after
const body = { method: 'GET' }; // or String(method).toUpperCase()
Defensive patterns

Strategy: type-guard

Validate before calling

const method = opts.method ?? 'GET';
if (typeof method !== 'string') throw new TypeError('method must be a string');

Type guard

function isMethodString(v) {
  return typeof v === 'string';
}

Try / catch

try {
  return await proxy({ url, method });
} catch (e) {
  if (e.status === 400 && /Invalid method/.test(e.message)) {
    console.error('method must be a string like "GET"');
  }
  throw e;
}

Prevention

When it happens

Trigger: POSTing to the proxy with body { method: 200 } or { method: { ... } } — any non-string value for method.

Common situations: Auto-generated clients serializing method as a number (e.g. a status code); a config value passed through unvalidated; copy-pasted body using wrong field types.

Related errors


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