shareAI-lab/learn-claude-code · error · WorkflowInputError

could not allocate a unique workflow runId

Error message

could not allocate a unique workflow runId

What it means

reserve_run_id tries up to 32 times to create <runId>.json with O_CREAT|O_EXCL (atomic create-if-absent). Every attempt collided with an existing file, so no unique identity could be reserved and WorkflowInputError is raised before any journal is touched. Run ids embed 16 random hex characters (secrets.token_hex(8)), so 32 straight collisions indicate the filesystem or id generation is degenerate rather than bad luck.

Source

Thrown at s16_workflow_runtime/code.py:66


def create_run_id(meta) -> str:
    return f"wf_{meta['name']}_{secrets.token_hex(8)}"


def reserve_run_id(meta) -> str:
    """Reserve a fresh run identity before any journal can be truncated."""
    STORE.mkdir(parents=True, exist_ok=True)
    for _ in range(32):
        run_id = validate_run_id(create_run_id(meta))
        snapshot_path = STORE / f"{run_id}.json"
        try:
            fd = os.open(snapshot_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
        except FileExistsError:
            continue
        os.close(fd)
        return run_id
    raise WorkflowInputError("could not allocate a unique workflow runId")


def create_task_id(run_id) -> str:
    return f"local_workflow_{run_id}"


def validate_run_id(run_id):
    if not isinstance(run_id, str) or not RUN_ID_RE.fullmatch(run_id):
        raise WorkflowInputError("invalid workflow runId")
    return run_id


# -- Errors --
class WorkflowInputError(Exception):
    """Bad workflow, metadata, or schema input."""


_run_locks_guard = threading.Lock()

View on GitHub (pinned to 985456f4ad)

Solutions

  1. If tests stub secrets.token_hex, ensure the stub yields distinct values per call
  2. Point STORE at a clean writable directory for the run
  3. Clear stale <runId>.json placeholder files if a previous run crashed between reservation and journal write

Example fix

# before (test stub breaks uniqueness)
monkeypatch.setattr(secrets, "token_hex", lambda n: "deadbeefdeadbeef")

# after
values = iter(["aa11" * 4, "bb22" * 4])
monkeypatch.setattr(secrets, "token_hex", lambda n: next(values))
Defensive patterns

Strategy: retry

Validate before calling

from pathlib import Path

def store_is_clean(store: Path) -> bool:
    # placeholder collisions are the only realistic failure; ensure the dir is writable
    return store.is_dir() or store.parent.is_dir()

assert store_is_clean(STORE)

Try / catch

for attempt in range(3):
    try:
        run_id = reserve_run_id(meta)
        break
    except WorkflowInputError:
        if attempt == 2:
            raise
        # deterministic-id test stub or polluted store; fix the source, then retry

Prevention

When it happens

Trigger: A monkeypatched or seeded secrets.token_hex in tests returning constant values. A STORE directory pre-populated with files matching wf_<name>_<hex>.json for the exact hex values generated (e.g. replaying a captured id sequence). Filesystem issues where O_EXCL is unsupported and open always reports EEXIST.

Common situations: Test suites that stub randomness without uniqueness. Restoring a store from a snapshot and rerunning with a deterministic RNG. Exotic network filesystems with broken O_EXCL semantics.

Related errors


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/cd1b8e8e4b2e1cd1. Report an issue: GitHub.