{"record":{"id":"1eb6ca72fd45c6d9","repo":"mem0ai/mem0","slug":"mem0-api-key-must-be-a-string","errorCode":null,"errorMessage":"Mem0 API key must be a string","messagePattern":"Mem0 API key must be a string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/client/mem0.ts","lineNumber":114,"sourceCode":"const identityByCredentials = new Map<string, Promise<ClientIdentity>>();\n\nexport default class MemoryClient {\n  apiKey: string;\n  host: string;\n  private organizationId: string | number | null;\n  private projectId: string | number | null;\n  headers: Record<string, string>;\n  client: any;\n  telemetryId: string;\n  private initialized: Promise<void>;\n  private identityCacheMax: number;\n\n  _validateApiKey(): any {\n    if (!this.apiKey) {\n      throw new Error(\"Mem0 API key is required\");\n    }\n    if (typeof this.apiKey !== \"string\") {\n      throw new Error(\"Mem0 API key must be a string\");\n    }\n    if (this.apiKey.trim() === \"\") {\n      throw new Error(\"Mem0 API key cannot be empty\");\n    }\n  }\n\n  constructor(options: ClientOptions) {\n    this.apiKey = options.apiKey;\n    this.host = options.host || \"https://api.mem0.ai\";\n    this.organizationId = null;\n    this.projectId = null;\n    this.identityCacheMax =\n      options.identityCacheMax ?? IDENTITY_CACHE_MAX_DEFAULT;\n\n    this.headers = {\n      Authorization: `Token ${this.apiKey}`,\n      \"Content-Type\": \"application/json\",\n    };","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/client/mem0.ts#L96-L132","documentation":"The second branch of _validateApiKey() throws when apiKey is present but not a string — e.g. a number, object, or array. TypeScript types say string, but at runtime (JS callers, JSON configs, env coercion) a non-string can reach the client, and the header-building code would produce garbage auth, so the client rejects it up front.","triggerScenarios":"Passing apiKey: 12345, apiKey: { token: '...' }, or a Buffer; reading the key from a JSON config as a number; a proxy layer forwarding the key as a non-string type.","commonSituations":"Numeric-looking keys stored unquoted in JSON/YAML; JWE/JWT objects passed where the raw string is expected; JS callers bypassing the TS types.","solutions":["Pass the raw string: apiKey: String(process.env.MEM0_API_KEY).","Quote the value in JSON/YAML config files so it parses as a string.","If the key arrives as an object (e.g. {token}), extract the string field before constructing the client."],"exampleFix":"// before\nconst client = new MemoryClient({ apiKey: config.mem0_key }); // config.mem0_key = 4815162342\n\n// after\nconst client = new MemoryClient({ apiKey: String(config.mem0_key) });","handlingStrategy":"type-guard","validationCode":"const asApiKeyString = (v: unknown): string => {\n  if (typeof v === 'string') return v;\n  throw new Error(`apiKey must be a string, got ${typeof v}`);\n};\n\nnew MemoryClient({ apiKey: asApiKeyString(config.mem0_key) });","typeGuard":"const isStringApiKey = (v: unknown): v is string => typeof v === 'string';","tryCatchPattern":null,"preventionTips":["Quote API key values in JSON/YAML so they never parse as numbers.","If the key may arrive as an object, extract the string field explicitly before construction.","Validate external config with a schema (zod .string()) before passing to the client."],"tags":["validation","api-key","type-coercion"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}