Mintplex-Labs/anything-llm · error

Failed integrity signature check.

Error message

Failed integrity signature check.

What it means

Collector middleware verifyPayloadIntegrity rejects any request missing the X-Integrity header when NODE_ENV is not 'development'. Every collector API call must carry an HMAC signature computed over the exact request body with the instance communication key; absence yields 400 'Failed integrity signature check.'.

Source

Thrown at collector/middleware/verifyIntegrity.js:17

const { CommunicationKey } = require("../utils/comKey");
const RuntimeSettings = require("../utils/runtimeSettings");
const runtimeSettings = new RuntimeSettings();

function verifyPayloadIntegrity(request, response, next) {
  const comKey = new CommunicationKey();
  if (process.env.NODE_ENV === "development") {
    comKey.log("verifyPayloadIntegrity is skipped in development.");
    runtimeSettings.parseOptionsFromRequest(request);
    next();
    return;
  }

  const signature = request.header("X-Integrity");
  if (!signature)
    return response
      .status(400)
      .json({ msg: "Failed integrity signature check." });

  const validSignedPayload = comKey.verify(signature, request.body);
  if (!validSignedPayload)
    return response
      .status(400)
      .json({ msg: "Failed integrity signature check." });

  runtimeSettings.parseOptionsFromRequest(request);
  next();
}

module.exports = {
  verifyPayloadIntegrity,
};

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Sign the exact request body with the instance communication key and send the result in the X-Integrity header, mirroring the built-in collector logic.
  2. For local testing only, run the collector with NODE_ENV=development so the middleware logs and skips — never do this in production.
  3. Ensure no proxy between client and collector strips the X-Integrity header.
  4. Confirm the header name capitalization and that it is sent on every collector API request.

Example fix

// before
await fetch(`${collectorUrl}/api/upload`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
}); // 400 Failed integrity signature check.

// after
const comKey = new CommunicationKey();
const body = JSON.stringify(payload);
await fetch(`${collectorUrl}/api/upload`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'X-Integrity': comKey.sign(body) },
  body,
});
Defensive patterns

Strategy: validation

Validate before calling

function hasIntegrityHeader(headers) {
  return typeof headers['X-Integrity'] === 'string' && headers['X-Integrity'].length > 0;
}
// Before sending to the collector:
if (!hasIntegrityHeader(reqHeaders)) throw new Error('Request must be signed (X-Integrity header missing).');

Try / catch

const res = await fetch(collectorUrl, opts);
if (res.status === 400) {
  const body = await res.json();
  if (body.msg === 'Failed integrity signature check.') {
    // Missing header or bad signature — do not retry blindly; fix signing first
    throw new Error('Collector rejected request: ' + (hasIntegrityHeader(opts.headers) ? 'signature mismatch' : 'X-Integrity header missing'));
  }
}

Prevention

When it happens

Trigger: Calling collector endpoints directly (curl, custom scripts, third-party integrations) without signing; sending the signature under a different header name; an intermediate proxy stripping the X-Integrity header; NODE_ENV left as production while testing by hand.

Common situations: Custom integration script hits the collector API and forgets header signing; corporate proxy removes custom headers; developer tests against a production-mode instance the way they tested in development mode (where the middleware is skipped).

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/330503a92cafc9e5. Report an issue: GitHub.