{"record":{"id":"6db09b4acc46f3a3","repo":"can1357/oh-my-pi","slug":"bedrock-http-response-status-errbody-slice-0","errorCode":null,"errorMessage":"Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}","messagePattern":"Bedrock HTTP (.+?): (.+?)","errorType":"exception","errorClass":"BedrockApiError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/amazon-bedrock.ts","lineNumber":488,"sourceCode":"\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: requestHeaders,\n\t\t\t\t\tbody,\n\t\t\t\t\tsignal: watchdog.signal,\n\t\t\t\t\tfetch: options.fetch,\n\t\t\t\t\ttimeout: false,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\twatchdog.clear();\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tif (!bearerToken && (response.status === 401 || response.status === 403)) {\n\t\t\t\t\t// Stale cached credentials (e.g. rotated session keys in ~/.aws/credentials) —\n\t\t\t\t\t// drop the cache entry so the next attempt re-resolves from scratch.\n\t\t\t\t\tinvalidateAwsCredentialCache({ profile: options.profile, region });\n\t\t\t\t}\n\t\t\t\tconst errBody = await response.text().catch(() => \"\");\n\t\t\t\tthrow new AIError.BedrockApiError(\n\t\t\t\t\t`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: response.headers,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.body) throw new AIError.BedrockApiError(\"Bedrock response has no body\", response.status);\n\n\t\t\t// Track first event for the abort/diagnostic path (currently informational).\n\t\t\tfor await (const message of decodeEventStream(response.body)) {\n\t\t\t\tconst messageType = message.headers[\":message-type\"];\n\t\t\t\tconst eventType = message.headers[\":event-type\"];\n\n\t\t\t\tif (messageType === \"exception\") {\n\t\t\t\t\tconst exceptionType = message.headers[\":exception-type\"] || \"Exception\";\n\t\t\t\t\tconst payload = safeParsePayload(message.payload) as { message?: string } | undefined;\n\t\t\t\t\tconst errorMessage = payload?.message || new TextDecoder().decode(message.payload);","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/amazon-bedrock.ts#L470-L506","documentation":"A BedrockApiError raised in streamBedrock when the Bedrock HTTP endpoint (event stream invocation) returns a non-success status. The message embeds the HTTP status and up to 1000 characters of the response body for diagnosis. For 401/403 without a bearer token, the AWS credential cache is invalidated first so the next attempt re-resolves credentials.","triggerScenarios":"Bedrock InvokeModelWithResponseStream returning 4xx/5xx; expired or rotated AWS session credentials causing 401/403; missing model access or wrong region giving 403/404; request throttling (429) or malformed request bodies (400).","commonSituations":"Stale ~/.aws/credentials after an SSO re-login; IAM policy lacking bedrock:InvokeModelWithResponseStream; model id not available in the selected region; quota exhaustion during bursts.","solutions":["Read the embedded body in the message — it contains Bedrock's actual error reason","For 401/403: re-run aws sso login / refresh credentials; the cache is auto-invalidated but the current attempt still fails","Verify IAM permissions for bedrock:InvokeModelWithResponseStream on the model ARN","Confirm the model id and region are correct and the model is enabled in your account","Implement retry with backoff for 429/5xx statuses"],"exampleFix":"// before\nconst res = await client.send(new InvokeModelWithResponseStreamCommand(input)); // throws on 403\n// after\ntry {\n  const res = await client.send(cmd);\n} catch (e) {\n  if (e instanceof AIError.BedrockApiError && e.status === 403) {\n    await refreshAwsCredentials(); // then retry once\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"// pre-check credentials and access before calling\nconst sts = new STSClient({ region });\nawait sts.send(new GetCallerIdentityCommand({})); // fails fast on bad creds\nif (!bearerToken && (!process.env.AWS_PROFILE && !options.profile)) console.warn(\"no explicit AWS profile set\");","typeGuard":"function isBedrockHttpError(e: unknown): e is AIError.BedrockApiError {\n  return e instanceof AIError.BedrockApiError && /^Bedrock HTTP \\d+/.test(e.message);\n}","tryCatchPattern":"try {\n  await streamBedrock(options);\n} catch (e) {\n  if (isBedrockHttpError(e)) {\n    const status = e.status;\n    if (status === 429 || status >= 500) return retryWithBackoff();\n    if (status === 401 || status === 403) return refreshAwsCredsAndRetry();\n  }\n  throw e;\n}","preventionTips":["Refresh AWS credentials proactively before expiry (SSO/token expiry windows)","Grant bedrock:InvokeModelWithResponseStream in IAM for the model ARNs you use","Enable the model in every region you call","Add backoff retry for 429/5xx only; fail fast on 400"],"tags":["aws","bedrock","http","auth"],"backgroundTag":"bedrock-http-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}