paperclipai/paperclip · error · Error

Unable to inspect protocol eval history object: ${detail.sli

Error message

Unable to inspect protocol eval history object: ${detail.slice(0, 400)}

What it means

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.

Source

Thrown at packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs:392

function awsObject(bucket, key) {
  return `s3://${bucket}/${key}`;
}

async function objectExists(bucket, key) {
  try {
    await execFileAsync("aws", [
      "s3api",
      "head-object",
      "--bucket",
      bucket,
      "--key",
      key,
    ]);
    return true;
  } catch (error) {
    const detail = String(error?.stderr ?? error?.message ?? error);
    if (/\b(?:404|Not Found|NoSuchKey)\b/iu.test(detail)) return false;
    throw new Error(
      `Unable to inspect protocol eval history object: ${detail.slice(0, 400)}`,
    );
  }
}

async function downloadJson(bucket, key, destination) {
  if (!(await objectExists(bucket, key))) return null;
  await execFileAsync("aws", [
    "s3",
    "cp",
    awsObject(bucket, key),
    destination,
    "--only-show-errors",
  ]);
  return loadObject(destination);
}

async function uploadFile(bucket, key, file, cacheControl) {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Run `aws s3api head-object --bucket <bucket> --key <key>` manually to see the real error
  2. Fix credentials: assume the CI role or export valid AWS credentials/profile
  3. Verify the bucket name, AWS_REGION, and network access (VPC endpoint/proxy) in the environment
  4. Grant s3:HeadObject (s3:GetObject) on the bucket/prefix to the publishing principal
  5. Ensure the aws CLI v2 is installed and on PATH

Example fix

// before
const { bucket } = destination; // empty in local shell
await objectExists(bucket, key); // -> Unable to inspect ... AccessDenied
// after
if (!process.env.RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET) throw new Error("set RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET");
await execFileAsync("aws", ["sts", "get-caller-identity"]); // sanity-check credentials first
Defensive patterns

Strategy: retry

Validate before calling

await execFileAsync("aws", ["sts", "get-caller-identity"]); // credentials ok?
if (!process.env.RUNNER_PROTOCOL_EVAL_HISTORY_S3_BUCKET) throw new Error("bucket env var unset");

Try / catch

try {
  await publishProtocolEvalHistory({ reportRoot, destination, viewerRoot });
} catch (e) {
  const msg = String(e.message);
  if (msg.includes("Unable to inspect protocol eval history object")) {
    if (/AccessDenied|ExpiredToken|NoCredentials/i.test(msg)) throw new Error("fix AWS credentials/permissions for head-object");
    if (/Networking|connect|timeout|ENOTFOUND/i.test(msg)) { /* retry with backoff */ }
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/ac34128c02f31aab. Report an issue: GitHub.