{"record":{"id":"67a0cbd1f9f7c1f3","repo":"Mintplex-Labs/anything-llm","slug":"e-message-67a0cb","errorCode":null,"errorMessage":"${e.message}","messagePattern":"\\$\\{e\\.message\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/AiProviders/togetherAi/index.js","lineNumber":195,"sourceCode":"      },\n    ];\n  }\n\n  async getChatCompletion(messages = null, { temperature = 0.7 }) {\n    if (!(await this.isValidChatCompletionModel(this.model)))\n      throw new Error(\n        `TogetherAI chat: ${this.model} is not valid for chat completion!`\n      );\n\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      !result.output.hasOwnProperty(\"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":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/AiProviders/togetherAi/index.js#L177-L213","documentation":"Re-thrown from the OpenAI SDK rejection inside TogetherAiLLM.getChatCompletion via `.catch((e) => { throw new Error(e.message); })`. The wrapper discards the SDK error class and HTTP status, so a 401 (auth), 429 (Together AI free-tier rate limits are common), and a server error look alike to the caller except for the message text.","triggerScenarios":"api.together.xyz returns non-2xx or the client throws pre-response: 401 invalid/expired key, 404 model not deployed, 429 rate/quota (Together's free tier is aggressive), 5xx, DNS/TLS/abort errors.","commonSituations":"Free-tier Together key hitting the per-minute request cap; key deactivated after startup; TOGETHER_AI_MODEL_PREF pointed at a model that passed local cache validation but is not enabled for the key; flaky network egress; client aborted the streaming request.","solutions":["Decode the message: '401'/'Unauthorized' -> key; '429'/'rate limit' -> throttle or upgrade tier; 'model'/'not found' -> model id; 'timeout'/'ECONN' -> network.","curl POST https://api.together.xyz/v1/chat/completions with the same key/model to isolate.","For 429, add bounded exponential-backoff retry and/or reduce concurrency.","Check the Together AI dashboard for quota/usage and model availability."],"exampleFix":"// before\nconst out = await llm.getChatCompletion(messages, { temperature: 0.7 });\n\n// after\nasync function togetherWithBackoff(llm, messages, opts, retries = 4) {\n  for (let i = 0; i <= retries; i++) {\n    try {\n      return await llm.getChatCompletion(messages, opts);\n    } catch (e) {\n      if (!/429|5\\d{2}|timeout|ECONN/i.test(e.message) || i === retries) throw e;\n      await new Promise((r) => setTimeout(r, 2 ** i * 500));\n    }\n  }\n}\nconst out = await togetherWithBackoff(llm, messages, { temperature: 0.7 });","handlingStrategy":"retry","validationCode":"function classifyTogetherError(message) {\n  if (/401|unauthorized|invalid api key/i.test(message)) return \"auth\";\n  if (/model|not found/i.test(message)) return \"model\";\n  if (/429|rate limit|quota/i.test(message)) return \"rate\"; // Together free tier is aggressive\n  if (/5\\d{2}|timeout|ECONN/i.test(message)) return \"transient\";\n  return \"fatal\";\n}","typeGuard":"function isTransientTogetherError(message) {\n  return typeof message === \"string\" && /429|5\\d{2}|timeout|ECONNRESET|fetch failed/i.test(message);\n}","tryCatchPattern":"async function togetherCall(llm, messages, opts, retries = 4) {\n  for (let i = 0; i <= retries; i++) {\n    try {\n      return await llm.getChatCompletion(messages, opts);\n    } catch (e) {\n      const kind = classifyTogetherError(e.message);\n      if (kind === \"auth\" || kind === \"model\" || i === retries) throw e;\n      await new Promise((r) => setTimeout(r, 2 ** i * 500)); // backoff for rate/transient\n    }\n  }\n}","preventionTips":["Together AI's free tier rate-limits hard — set conservative concurrency and per-minute caps.","Preserve the SDK error with { cause: e } since the wrapper drops the status code.","Classify errors so auth/model failures fail fast and only rate/transient retry.","Check the Together dashboard quota before assuming a code defect."],"tags":["runtime","api-error","llm-provider","togetherai","network","error-wrapping"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}