{"record":{"id":"6fb6155478667b8d","repo":"Mintplex-Labs/anything-llm","slug":"e-message-6fb615","errorCode":null,"errorMessage":"e.message","messagePattern":"e\\.message","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/AiProviders/moonshotAi/index.js","lineNumber":121,"sourceCode":"    ];\n  }\n\n  async compressMessages(promptArgs = {}, rawHistory = []) {\n    const { messageArrayCompressor } = require(\"../../helpers/chat\");\n    const messageArray = this.constructPrompt(promptArgs);\n    return await messageArrayCompressor(this, messageArray, rawHistory);\n  }\n\n  async getChatCompletion(messages = null, { temperature = 0.7 }) {\n    const result = await LLMPerformanceMonitor.measureAsyncFunction(\n      this.openai.chat.completions\n        .create({\n          model: this.model,\n          messages,\n          temperature,\n        })\n        .catch((e) => {\n          throw new Error(e.message);\n        })\n    );\n\n    if (\n      !Object.prototype.hasOwnProperty.call(result.output, \"choices\") ||\n      result.output.choices.length === 0\n    )\n      return null;\n\n    return {\n      textResponse: result.output.choices[0].message.content,\n      metrics: {\n        prompt_tokens: result.output.usage.prompt_tokens || 0,\n        completion_tokens: result.output.usage.completion_tokens || 0,\n        total_tokens: result.output.usage.total_tokens || 0,\n        outputTps: result.output.usage.completion_tokens / result.duration,\n        duration: result.duration,\n        model: this.model,","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/AiProviders/moonshotAi/index.js#L103-L139","documentation":"Same re-wrap anti-pattern: getChatCompletion's .catch flattens any upstream Moonshot API error to a plain Error(e.message). Note Moonshot's getChatCompletion skips the isValidChatCompletionModel pre-check entirely (unlike Minimax/Mistral/Novita) and goes straight to the call, then returns null on a choices-less response. So this catch is the only error boundary for the request.","triggerScenarios":"Any upstream failure from openai.chat.completions.create against api.moonshot.ai: 401, 429, 400 (e.g. context length exceeded on moonshot-v1-8k/32k), timeout, or 5xx.","commonSituations":"Invalid Moonshot key; exceeding the model's context window (Moonshot enforces per-model token limits); rate limiting; transient outage; the re-wrap hiding whether it was a context-length error vs auth.","solutions":["Read the message for the upstream detail (often includes the real cause).","If context-length related, switch to moonshot-v1-32k or 128k, or trim history.","If auth-related, verify MOONSHOT_AI_API_KEY.","Add backoff/retry for 429/5xx text."],"exampleFix":"// before\n.catch((e) => {\n  throw new Error(e.message);\n})\n\n// after\n.catch((e) => {\n  const err = new Error(`Moonshot chat failed (${e?.status}): ${e.message}`);\n  err.cause = e;\n  err.status = e?.status;\n  throw err;\n})","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await llm.getChatCompletion(messages, { temperature });\n} catch (e) {\n  const msg = e.message || '';\n  if (/context.*(length|window)|too many tokens/i.test(msg)) { /* trim history or use a larger model */ }\n  else if (/429|rate/i.test(msg)) { /* backoff */ }\n  else if (/401|api key/i.test(msg)) { /* rotate key */ }\n}","preventionTips":["Pick the right moonshot-v1 window (8k/32k/128k) for your history size — Moonshot enforces it strictly.","Patch the catch to retain e.status/e.cause.","Compress chat history before sending to stay under the limit."],"tags":["moonshot","error-handling","openai-client","anti-pattern","context-length"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}