ErrLookupBackground articles › "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them

"invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them

"Invalid id", "invalid identifier", and "invalid block ID" errors are format-validation failures: a library rejects an identifier because its shape doesn't match the expected pattern — wrong prefix, wrong length, illegal characters, or path-unsafe input — before it ever searches for the object. Developers hit them when hand-crafting IDs, pasting from URLs or markdown, or passing the wrong ID type entirely. This article explains why so many libraries validate ID format up front, what the common pattern violations look like across Go, Ruby, Rust, TypeScript, PHP, and Java projects, and how to fix and prevent them.

Distilled from 103 documented records across 37 repositories.

Background

This family covers a guard that appears at almost every layer of modern software: a function receives an identifier, checks it against a pattern — a regex, a length-and-charset rule, a prefix convention — and refuses to proceed when the shape is wrong. Crucially, the rejection happens before any lookup. SiYuan's model.ErrInvalidID is explicit about this distinction: a malformed attribute-view or block ID never reaches the blocktree, so the error means 'bad format', not 'not found' (match it with errors.Is to tell the two apart). Ubicloud's SDK validates inference API keys against \Aak[a-tv-z0-9]{24}\z client-side before any request, and Hmbown/CodeWhale's preallocated task-id check (task_ + 16 hex chars) exists because a collision would silently overwrite persisted records. These are deliberate fail-fast designs: a wrong-shaped ID can never exist server-side, so attempting the operation would be pointless at best and dangerous at worst.

The dangerous part of the family is path and URL safety. Several validations exist not for correctness but because the identifier gets interpolated into a filesystem path or a REST URL. Ubicloud rejects SSH public key strings containing '/' because the value is placed into the path ssh-public-key/<value> — a slash would corrupt or traverse the URL. Mastra's sandbox worker restricts executionId to letters, digits, dots, underscores, and hyphens because the id is used to build filesystem paths and shell arguments. openhuman's draft-id rule (non-empty, ≤64 chars, ASCII alphanumerics, '-' and '_' only) exists purely because an unvalidated path join would let '../' escape the drafts directory. In these cases the 'invalid id' error is a security boundary, and libraries intentionally accept only a narrow allowlist rather than trying to blacklist traversal sequences.

From the caller's side, these errors usually mean the ID never came from the system that mints IDs. The recurring advice across records is to source identifiers from the system's own listing or lookup endpoints — SiYuan's lsNotebooks and getBlockKramdownID, Ubicloud's ai api-key list, Semantic Scholar's search — instead of constructing them. Typical bad inputs are predictable: a document path or notebook folder name where an ID belongs, a raw numeric ID where a PHID is required (Phabricator's PHID-PCD- column check), a full resource URL pasted where a bare id was expected, an ID with whitespace or zero-width characters from copy-paste, or a mismatched prefix such as passing an sk- SSH key id where an ak- inference key is expected.

The exact rules are library-specific and sometimes even inconsistent within one project. Ubicloud's SDK excludes 'u' from its ID alphabet ([a-tv-z0-9]) while its CLI checks the looser [a-z0-9]{24}, so an id containing 'u' can pass the CLI yet fail the SDK. SiYuan's block IDs are 14 digits plus 7 lowercase alphanumeric characters (22 total) while its session ids are exactly 20 chars of [0-9a-z]; its update APIs reject the whole batch for one bad ID with no element index in the message. Claude-mem's mode ids enforce kebab-case with at most one '--' inheritance separator. The pattern to internalize is the mechanism, not any single regex: validate the shape, include the offending value in the message, and reject before lookup, disk, or network.

Common causes

What usually fixes it

Go deeper

Documented occurrences

…and 83 more across the corpus — use search.

Honest provenance: generated on 2026-08-31 from AI-assisted analysis of the linked records. See how records are made.