{"record":{"id":"67b09c4d4d613c56","repo":"chroma-core/chroma","slug":"unprocessable-entity","errorCode":null,"errorMessage":"Unprocessable Entity","messagePattern":"Unprocessable Entity","errorType":"http","errorClass":"ChromaClientError","httpStatus":422,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/chroma-fetch.ts","lineNumber":119,"sourceCode":"        throw new ChromaStaleReadError(\n          preconditionBody.message || \"stale read\",\n        );\n      }\n      throw new ChromaClientError(\n        preconditionBody.message || \"Precondition Failed\",\n      );\n    case 422:\n      try {\n        const body = await response.json();\n        if (\n          body &&\n          body.message &&\n          (body.message.startsWith(\"Quota exceeded\") ||\n            body.message.startsWith(\"Billing limit exceeded\"))\n        ) {\n          throw new ChromaQuotaExceededError(body?.message);\n        }\n        throw new ChromaClientError(body?.message || \"Unprocessable Entity\");\n      } catch (error) {\n        if (\n          error instanceof ChromaQuotaExceededError ||\n          error instanceof ChromaClientError\n        ) {\n          throw error;\n        }\n        throw new ChromaClientError(\n          `Unprocessable Entity: ${response.statusText}`,\n        );\n      }\n    case 429:\n      const rateLimitBody = await getErrorBody(response);\n      if (rateLimitBody.error === \"Backoff\") {\n        throw new ChromaBackoffError(\n          rateLimitBody.message || \"Backoff and retry\",\n        );\n      }","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/chroma-fetch.ts#L101-L137","documentation":"Thrown by chromaFetch (chroma-fetch.ts:119) as a ChromaClientError when the server returns 422, the JSON body parses, but it carries no usable `message` field and none of the quota/billing prefixes match. The server rejected the request as semantically invalid (well-formed but unacceptable content), and the library falls back to the bare status text.","triggerScenarios":"Semantic validation failures server-side: invalid embedding function configuration, malformed metadata values, inconsistent document/embedding array lengths, or any 422 whose error body uses a different shape than {message}.","commonSituations":"Version skew where an older server emits differently shaped 422 bodies; hand-built payloads skipping required fields; custom server middleware returning 422 without a message.","solutions":["Inspect the raw response by reproducing the request with curl to see the server's full 422 body.","Align client and server versions so error payloads and API contracts match.","Validate payload invariants client-side (equal-length ids/documents/embeddings/metadata arrays, valid metadata value types).","Check the collection's embedding configuration against the data you send."],"exampleFix":"// before\nawait collection.add({ ids: [\"1\", \"2\"], documents: [\"only-one\"] }); // length mismatch => 422\n\n// after\nawait collection.add({ ids: [\"1\", \"2\"], documents: [\"first\", \"second\"] });","handlingStrategy":"validation","validationCode":"function assertBatchShape(b: { ids: string[]; documents?: string[]; embeddings?: number[][]; metadatas?: object[] }) {\n  const n = b.ids.length;\n  if (b.documents && b.documents.length !== n) throw new Error(\"documents length mismatch\");\n  if (b.embeddings && b.embeddings.length !== n) throw new Error(\"embeddings length mismatch\");\n  if (b.metadatas && b.metadatas.length !== n) throw new Error(\"metadatas length mismatch\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await collection.add(batch);\n} catch (e) {\n  if (e instanceof ChromaClientError && e.message === \"Unprocessable Entity\") {\n    // server gave no message: reproduce with curl to read the raw 422 body\n  }\n  throw e;\n}","preventionTips":["Validate array-length and type invariants client-side before every add/upsert.","Keep client/server versions aligned so 422 bodies carry actionable messages.","Log the raw response body in debug wrappers when the library's message is bare."],"tags":["http-422","validation","server-response","payload"],"backgroundTag":"semantic-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}