{"record":{"id":"15c7f8b63df8d694","repo":"danny-avila/LibreChat","slug":"path-must-be-a-non-empty-string","errorCode":null,"errorMessage":"${path} must be a non-empty string","messagePattern":"(.+?) must be a non-empty string","errorType":"validation","errorClass":"AgentRunEnvelopeError","httpStatus":null,"severity":"error","filePath":"packages/api/src/agents/envelope.ts","lineNumber":89,"sourceCode":"type CreateChatCompletionRunEnvelopeInput = Extract<\n  CreateAgentRunEnvelopeInput,\n  { protocol: 'chat.completions' }\n>;\ntype CreateResponsesRunEnvelopeInput = Extract<\n  CreateAgentRunEnvelopeInput,\n  { protocol: 'responses' }\n>;\n\nexport class AgentRunEnvelopeError extends TypeError {\n  constructor(message: string) {\n    super(message);\n    this.name = 'AgentRunEnvelopeError';\n  }\n}\n\nfunction assertNonEmptyString(value: string | undefined, path: string): string {\n  if (typeof value !== 'string' || value.trim().length === 0) {\n    throw new AgentRunEnvelopeError(`${path} must be a non-empty string`);\n  }\n  return value;\n}\n\nfunction cloneJsonValue<T>(value: T, path: string, ancestors: WeakSet<object>, depth: number): T;\nfunction cloneJsonValue(\n  value: unknown,\n  path: string,\n  ancestors: WeakSet<object>,\n  depth: number,\n): unknown {\n  if (depth > AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH) {\n    throw new AgentRunEnvelopeError(\n      `${path} exceeds the maximum nesting depth of ${AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH}`,\n    );\n  }\n\n  if (value === null || typeof value === 'string' || typeof value === 'boolean') {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/envelope.ts#L71-L107","documentation":"assertNonEmptyString inside the agent-run envelope builder rejects any value that is not a string or is empty after trim. It guards principal.id (required), and principal.role / principal.tenantId when present. The thrown AgentRunEnvelopeError is a TypeError subclass, so it can be narrowed with instanceof.","triggerScenarios":"Calling createAgentRunEnvelope with principal.id undefined/null/''; passing principal.role as a number; a request where req.user.id was not populated upstream.","commonSituations":"An unauthenticated request reaching the envelope builder; a middleware order bug where req.user is not yet attached; passing a numeric role where a string is required; trimming an all-whitespace id.","solutions":["Ensure the request is authenticated and req.user.id is set before constructing the envelope.","Pass role/tenantId only when they are real strings; omit them otherwise (they are optional).","Catch AgentRunEnvelopeError specifically at the seam and return 401/400."],"exampleFix":"// before\nconst envelope = createAgentRunEnvelope({\n  protocol: 'chat.completions',\n  requestId,\n  receivedAt: Date.now(),\n  principal: req.user, // id may be undefined\n  payload,\n});\n\n// after\nif (!req.user?.id) throw new Error('Authenticated user required');\nconst envelope = createAgentRunEnvelope({\n  protocol: 'chat.completions',\n  requestId,\n  receivedAt: Date.now(),\n  principal: { id: req.user.id, role: req.user.role, tenantId: req.user.tenantId },\n  payload,\n});","handlingStrategy":"validation","validationCode":"function assertNonEmptyString(v: unknown, path: string): string {\n  if (typeof v !== 'string' || v.trim().length === 0) {\n    throw new Error(`${path} must be a non-empty string`);\n  }\n  return v;\n}\nassertNonEmptyString(req.user?.id, 'principal.id');","typeGuard":"const isNonEmptyString = (v: unknown): v is string =>\n  typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"import { AgentRunEnvelopeError } from '~/agents/envelope';\ntry {\n  envelope = createAgentRunEnvelope(input);\n} catch (error) {\n  if (error instanceof AgentRunEnvelopeError) {\n    return res.status(400).json({ error: error.message });\n  }\n  throw error;\n}","preventionTips":["Authenticate and populate req.user.id before envelope construction.","Omit optional principal.role / tenantId when they are not real strings.","Catch AgentRunEnvelopeError at the seam and map to 4xx."],"tags":["agents","envelope","validation","typescript","auth"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}