earendil-works/pi · error
Session id must be non-empty, contain only alphanumeric…
Error message
Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character
What it means
Validation guard in assertValidSessionId: the given session id fails the pattern ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ — it is empty, contains characters other than alphanumerics, '-', '_', '.', or starts/ends with a non-alphanumeric. Called on session creation, fork, and id CLI validation, so the offending input is a user-supplied or flag-provided session id.
Solutions
- Pass a session id matching the allowed pattern (alphanumeric start/end, only '.', '-', '_' inside)
- Use the generated uuidv7 id from createSessionId instead of a hand-written one
- For forkFrom, use the id of an existing session
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/coding-agent/src/core/session-manager.ts:214 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/ea80156e8d60e2d8.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/core/session-manager.ts:214
| "getLeafId"
| "getLeafEntry"
| "getEntry"
| "getLabel"
| "getBranch"
| "buildContextEntries"
| "getHeader"
| "getEntries"
| "getTree"
| "getSessionName"
>;
function createSessionId(): string {
return uuidv7();
}
export function assertValidSessionId(id: string): void {
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
throw new Error(
"Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character",
);
}
}
/** Generate a unique short ID (8 hex chars, collision-checked) */
function generateId(byId: { has(id: string): boolean }): string {
for (let i = 0; i < 100; i++) {
const id = randomUUID().slice(0, 8);
if (!byId.has(id)) return id;
}
// Fallback to full UUID if somehow we have collisions
return randomUUID();
}
/** Migrate v1 → v2: add id/parentId tree structure. Mutates in place. */
function migrateV1ToV2(entries: FileEntry[]): void {
const ids = new Set<string>();View on GitHub (pinned to 4af9d21d3b)