paperclipai/paperclip · error · Error

Evalbook attempt identity is empty

Error message

Evalbook attempt identity is empty

What it means

safeSegment normalizes an Evalbook attempt identity (e.g. attempt ID or candidate name) into a safe path segment and throws when the sanitized result is empty. The error means the identity input was empty, whitespace-only, or consisted entirely of characters stripped by the sanitizer.

Source

Thrown at packages/paperclip-runner/scripts/render-runner-workflow-evalbook.mjs:22

import { resolve } from "node:path";

const EVAL_PROGRAM_RELATIVE_PATH =
  "evals/paperclip-runner/tools/eval_program.py";

function json(value) {
  return `${JSON.stringify(value, null, 2)}\n`;
}

function sha256(value) {
  return createHash("sha256").update(value).digest("hex");
}

function safeSegment(value) {
  const segment = String(value)
    .trim()
    .replaceAll(/[^0-9A-Za-z._-]+/g, "-")
    .replaceAll(/^-+|-+$/g, "");
  if (!segment) throw new Error("Evalbook attempt identity is empty");
  return segment;
}

function candidateDescriptor(report, candidateId) {
  const descriptor =
    report.bundle.providerVersions?.[candidateId] ?? candidateId;
  const separator = descriptor.indexOf(":");
  return separator < 0
    ? { driver: "unknown driver", model: descriptor }
    : {
        driver: descriptor.slice(0, separator),
        model: descriptor.slice(separator + 1),
      };
}

function scoreChecks(result) {
  const dimensionChecks = Object.values(result.scorecard.dimensions).map(
    (dimension) => ({

View on GitHub (pinned to 01ad858492)

Solutions

  1. Ensure the attempt/candidate identifier is a non-empty meaningful value before rendering
  2. Log the raw value passed to safeSegment to see what sanitized to empty
  3. Fix the upstream report so the identity field is populated
  4. If ids can legitimately be blank, provide a default like 'unknown-attempt' at the call site

Example fix

// before
safeSegment(report.attemptId); // ''
// after
safeSegment(report.attemptId || 'unknown-attempt');
Defensive patterns

Strategy: validation

Validate before calling

if (!String(value ?? '').trim()) throw new Error('Attempt identity is empty');

Type guard

const hasIdentity = (v) => typeof v === 'string' && v.trim().length > 0;

Try / catch

try { const seg = safeSegment(id); } catch (e) { if (e.message.includes('identity is empty')) console.error('Attempt id was:', JSON.stringify(id)); throw e; }

Prevention

When it happens

Trigger: Passing an attempt id like '///', '---', or '' (undefined coerces to 'undefined' so usually passes); a candidate id that is only spaces or symbols.

Common situations: A workflow report with a missing/blank attempt field; upstream data change where the identifier field was renamed and now reads undefined-but-coerced or stripped-clean to nothing; manual runs passing a placeholder value.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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