{"record":{"id":"ac34128c02f31aab","repo":"paperclipai/paperclip","slug":"unable-to-inspect-protocol-eval-history-object","errorCode":null,"errorMessage":"Unable to inspect protocol eval history object: ${detail.slice(0, 400)}","messagePattern":"Unable to inspect protocol eval history object: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs","lineNumber":392,"sourceCode":"function awsObject(bucket, key) {\n  return `s3://${bucket}/${key}`;\n}\n\nasync function objectExists(bucket, key) {\n  try {\n    await execFileAsync(\"aws\", [\n      \"s3api\",\n      \"head-object\",\n      \"--bucket\",\n      bucket,\n      \"--key\",\n      key,\n    ]);\n    return true;\n  } catch (error) {\n    const detail = String(error?.stderr ?? error?.message ?? error);\n    if (/\\b(?:404|Not Found|NoSuchKey)\\b/iu.test(detail)) return false;\n    throw new Error(\n      `Unable to inspect protocol eval history object: ${detail.slice(0, 400)}`,\n    );\n  }\n}\n\nasync function downloadJson(bucket, key, destination) {\n  if (!(await objectExists(bucket, key))) return null;\n  await execFileAsync(\"aws\", [\n    \"s3\",\n    \"cp\",\n    awsObject(bucket, key),\n    destination,\n    \"--only-show-errors\",\n  ]);\n  return loadObject(destination);\n}\n\nasync function uploadFile(bucket, key, file, cacheControl) {","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs#L374-L410","documentation":"objectExists probes S3 with `aws s3api head-object` and treats only 404/Not Found/NoSuchKey as a benign \"does not exist\" answer. Any other failure (credentials, networking, permissions, malformed bucket) is wrapped in this error with up to 400 characters of the AWS CLI's stderr, because the publisher cannot distinguish absent history from a broken environment.","triggerScenarios":"Running publishProtocolEvalHistory without valid AWS credentials (aws CLI returns AccessDenied/ExpiredToken); no network or VPC endpoint to S3; IAM policy lacking s3:HeadObject on the bucket; bucket name typo so the request fails with a non-404 error; aws CLI not installed so execFile itself fails and surfaces here.","commonSituations":"CI job missing OIDC role assumption or AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY; regional misconfiguration (wrong AWS_REGION/endpoint); bucket exists in another account without cross-account read permission.","solutions":["Run `aws s3api head-object --bucket <bucket> --key <key>` manually to see the real error","Fix credentials: assume the CI role or export valid AWS credentials/profile","Verify the bucket name, AWS_REGION, and network access (VPC endpoint/proxy) in the environment","Grant s3:HeadObject (s3:GetObject) on the bucket/prefix to the publishing principal","Ensure the aws CLI v2 is installed and on PATH"],"exampleFix":"// before\nconst { bucket } = destination; // empty in local shell\nawait objectExists(bucket, key); // -> Unable to inspect ... AccessDenied\n// after\nif (!process.env.RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET) throw new Error(\"set RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET\");\nawait execFileAsync(\"aws\", [\"sts\", \"get-caller-identity\"]); // sanity-check credentials first","handlingStrategy":"retry","validationCode":"await execFileAsync(\"aws\", [\"sts\", \"get-caller-identity\"]); // credentials ok?\nif (!process.env.RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET) throw new Error(\"bucket env var unset\");","typeGuard":null,"tryCatchPattern":"try {\n  await publishProtocolEvalHistory({ reportRoot, destination, viewerRoot });\n} catch (e) {\n  const msg = String(e.message);\n  if (msg.includes(\"Unable to inspect protocol eval history object\")) {\n    if (/AccessDenied|ExpiredToken|NoCredentials/i.test(msg)) throw new Error(\"fix AWS credentials/permissions for head-object\");\n    if (/Networking|connect|timeout|ENOTFOUND/i.test(msg)) { /* retry with backoff */ }\n  }\n  throw e;\n}","preventionTips":["Assume the CI IAM role (OIDC) before the publish step and grant s3:HeadObject/GetObject on the prefix","Pin AWS_REGION and verify network/VPC endpoint access to S3","Smoke-test with `aws s3api head-object` in the same job before publishing","Ensure the aws CLI v2 is installed in the publish environment"],"tags":["aws","s3","network","credentials"],"backgroundTag":"http-error-response","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}