{"record":{"id":"d31e6473fb364ee5","repo":"danny-avila/LibreChat","slug":"reading-file-path-exceeded-the-sandbox-stdout","errorCode":null,"errorMessage":"Reading \"${file_path}\" exceeded the sandbox stdout limit (chunk ${chunkBytes} bytes). Lower LIBRECHAT_CODE_IMAGE_CHUNK_BYTES or raise SANDBOX_OUTPUT_MAX_SIZE on the runner.","messagePattern":"Reading \"(.+?)\" exceeded the sandbox stdout limit \\(chunk (.+?) bytes\\)\\. Lower LIBRECHAT_CODE_IMAGE_CHUNK_BYTES or raise SANDBOX_OUTPUT_MAX_SIZE on the runner\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/server/services/Files/Code/process.js","lineNumber":1397,"sourceCode":"      method: 'post',\n      url: `${baseURL}/exec`,\n      data: postData,\n      headers: {\n        'Content-Type': 'application/json',\n        'User-Agent': 'LibreChat/1.0',\n        ...authHeaders,\n      },\n      httpAgent: codeServerHttpAgent,\n      httpsAgent: codeServerHttpsAgent,\n      timeout: 15000,\n    });\n    const result = response?.data ?? {};\n    /* The runner truncates stdout at SANDBOX_OUTPUT_MAX_SIZE and SIGKILLs the\n     * job (status `OL`). Detect that explicitly: the surviving stdout is a\n     * base64 string cut mid-flight, so parsing it yields a misleading\n     * \"unexpected output\" instead of naming the real, fixable cause. */\n    if (result.status === 'OL') {\n      throw new Error(\n        `Reading \"${file_path}\" exceeded the sandbox stdout limit (chunk ${chunkBytes} bytes). ` +\n          'Lower LIBRECHAT_CODE_IMAGE_CHUNK_BYTES or raise SANDBOX_OUTPUT_MAX_SIZE on the runner.',\n      );\n    }\n    if (result.stderr && (result.stdout == null || result.stdout === '')) {\n      throw new Error(String(result.stderr).trim());\n    }\n    if (result.stdout == null || String(result.stdout).trim() === '') {\n      return {};\n    }\n    /* Parse the LAST non-empty line: the reader's JSON is the final thing it\n     * prints, so anything a shell profile or library emitted ahead of it\n     * (banners, warnings) must not break the read. */\n    const lines = String(result.stdout)\n      .split('\\n')\n      .map((line) => line.trim())\n      .filter(Boolean);\n    try {","sourceCodeStart":1379,"sourceCodeEnd":1415,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/Files/Code/process.js#L1379-L1415","documentation":"Thrown by execSandboxImageChunk (Code/process.js) when the sandbox runner reports status 'OL' (Output Limit): the chunk's stdout exceeded SANDBOX_OUTPUT_MAX_SIZE, so the runner truncated it and SIGKILLed the job. The surviving stdout is a base64 string cut mid-flight, so this explicit check names the real cause instead of letting JSON.parse fail with a confusing message.","triggerScenarios":"LIBRECHAT_CODE_IMAGE_CHUNK_BYTES is set large enough that the base64 of a single chunk exceeds the runner's SANDBOX_OUTPUT_MAX_SIZE; SANDBOX_OUTPUT_MAX_SIZE on the runner was lowered; reading a large image with an oversized chunk setting.","commonSituations":"Operator raised LIBRECHAT_CODE_IMAGE_CHUNK_BYTES to reduce round-trips without proportionally raising SANDBOX_OUTPUT_MAX_SIZE; runner config drifted from the API server config; newly deployed runner with a smaller default cap.","solutions":["Lower LIBRECHAT_CODE_IMAGE_CHUNK_BYTES so a single chunk's base64 fits under SANDBOX_OUTPUT_MAX_SIZE.","Or raise SANDBOX_OUTPUT_MAX_SIZE on the runner to accommodate the current chunk size.","Keep the two settings in a documented ratio (chunk base64 ≈ chunkBytes * 1.37, must be < SANDBOX_OUTPUT_MAX_SIZE).","After changing either, restart both the API server and the sandbox runner."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Keep chunk base64 under the runner cap before reading\nconst chunkBytes = Number(process.env.LIBRECHAT_CODE_IMAGE_CHUNK_BYTES);\nconst runnerCap = Number(process.env.SANDBOX_OUTPUT_MAX_SIZE);\nif (chunkBytes * 1.37 >= runnerCap) {\n  throw new Error('LIBRECHAT_CODE_IMAGE_CHUNK_BYTES too large for SANDBOX_OUTPUT_MAX_SIZE');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const img = await readSandboxImage({ file_path, session_id, req });\n} catch (err) {\n  if (/exceeded the sandbox stdout limit/.test(err.message)) {\n    // operator action: adjust config, not a code retry\n    logger.error('Config mismatch — adjust chunk/output caps', { chunkBytes, runnerCap });\n  }\n  throw err;\n}","preventionTips":["Keep LIBRECHAT_CODE_IMAGE_CHUNK_BYTES such that chunkBytes*1.37 < SANDBOX_OUTPUT_MAX_SIZE.","Document the ratio wherever one env var is documented.","Restart both API server and runner after changing either cap."],"tags":["code-env","sandbox","image","config","limits"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}