{"record":{"id":"6892141e45171e1a","repo":"ruvnet/ruflo","slug":"invalid-headers","errorCode":"INVALID_HEADERS","errorMessage":"headers must be an object","messagePattern":"headers must be an object","errorType":"validation","errorClass":"HttpFetchValidationError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts","lineNumber":199,"sourceCode":"      status: 0,\n      statusText: '',\n      headers: {},\n      body: '',\n      bodyTruncated: false,\n      bytesRead: 0,\n      durationMs: Date.now() - startedAt,\n      url,\n      method,\n      error: err.message,\n      errorCode: err.code ?? 'VALIDATION_ERROR',\n    };\n  }\n\n  let headers: Record<string, string>;\n  try {\n    const raw = (input.headers ?? {}) as Record<string, string>;\n    if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n      throw new HttpFetchValidationError('headers must be an object', 'INVALID_HEADERS');\n    }\n    headers = validateHeaders(raw);\n  } catch (e) {\n    const err = e as HttpFetchValidationError;\n    return {\n      success: false,\n      status: 0,\n      statusText: '',\n      headers: {},\n      body: '',\n      bodyTruncated: false,\n      bytesRead: 0,\n      durationMs: Date.now() - startedAt,\n      url,\n      method,\n      error: err.message,\n      errorCode: err.code ?? 'VALIDATION_ERROR',\n    };","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts#L181-L217","documentation":"Thrown by the http_fetch handler when input.headers is present but not a plain object — it is null, an array, or a primitive. Headers must be a Record<string,string>; the check runs before validateHeaders iterates entries. The error carries code INVALID_HEADERS.","triggerScenarios":"Passing headers as null, an array (e.g. [['a','b']]), a string, or a number. The guard `typeof raw !== 'object' || raw === null || Array.isArray(raw)` catches all three.","commonSituations":"Passing a header string like 'Authorization: Bearer x' instead of an object; sending a FormData or URLSearchParams instance that is object-like but not a plain record; defaulting headers to null when none are needed (omit the field instead).","solutions":["Pass headers as a plain object { key: 'value' } or omit the field entirely.","Convert header arrays/strings into an object before calling http_fetch.","Use {} as the default, not null, when conditionally building headers.","Type the headers parameter as Record<string,string> at the call site to catch this at compile time."],"exampleFix":"// before\nhttp_fetch({ url, headers: null })\n// after\nhttp_fetch({ url })  // omit when no headers are needed","handlingStrategy":"type-guard","validationCode":"function normalizeHeaders(raw) {\n  if (raw == null) return {};\n  if (typeof raw !== 'object' || Array.isArray(raw)) {\n    throw new Error('headers must be a plain object');\n  }\n  return raw;\n}","typeGuard":"function isPlainHeaderObject(h: unknown): h is Record<string, unknown> {\n  return typeof h === 'object' && h !== null && !Array.isArray(h);\n}","tryCatchPattern":null,"preventionTips":["Omit the headers field when none are needed instead of passing null.","Default to {} when building headers conditionally.","Type the parameter as Record<string,string>."],"tags":["http-fetch","headers","validation","input-validation","type-error"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}