can1357/oh-my-pi · error
unknown extraction tier ${JSON.stringify(tier)}; valid tiers
Error message
unknown extraction tier ${JSON.stringify(tier)}; valid tiers: ${EXTRACTION_TIERS.join(", ")} What it means
ExtractionDiagnostics.validateTier asserts the tier string is one of the known EXTRACTION_TIERS before recording an attempt/success/failure/no-output event. Unknown tier strings throw an Error listing the valid tiers, keeping diagnostics counters type-safe.
Source
Thrown at packages/mnemopi/src/core/extraction/diagnostics.ts:91
function errorRepr(exc: unknown): string {
if (exc instanceof Error) {
return `${exc.name}: ${exc.message}`;
}
return String(exc);
}
export class ExtractionDiagnostics {
private tierStats: Record<ExtractionTier, MutableTierStats> = emptyTierStats();
private totalCalls = 0;
private totalSuccesses = 0;
private totalFailures = 0;
private totalEmpty = 0;
private createdAt = new Date().toISOString();
private validateTier(tier: string): asserts tier is ExtractionTier {
if (!isTier(tier)) {
throw new Error(
`unknown extraction tier ${JSON.stringify(tier)}; valid tiers: ${EXTRACTION_TIERS.join(", ")}`,
);
}
}
recordAttempt(tier: ExtractionTier): void {
this.validateTier(tier);
this.tierStats[tier].attempts += 1;
}
recordSuccess(tier: ExtractionTier, _factCount = 0): void {
this.validateTier(tier);
this.tierStats[tier].successes += 1;
}
recordNoOutput(tier: ExtractionTier): void {
this.validateTier(tier);
this.tierStats[tier].no_output += 1;
}
recordFailure(tier: ExtractionTier, exc?: unknown, reason?: string): void {View on GitHub (pinned to 9690622007)
Solutions
- Use only tier names from EXTRACTION_TIERS (import the constant and iterate it instead of hardcoding).
- Type the tier parameter as ExtractionTier so invalid strings fail at compile time.
- Map/upgrade legacy tier labels before calling the diagnostics methods.
Example fix
// before
diag.recordAttempt("fast"); // suppose valid is "fast-path"
// after
import { EXTRACTION_TIERS } from "./tiers";
if (EXTRACTION_TIERS.includes(tier as ExtractionTier)) diag.recordAttempt(tier); Defensive patterns
Strategy: type-guard
Validate before calling
import { EXTRACTION_TIERS } from "./diagnostics";
function isTier(t: string): t is ExtractionTier {
return (EXTRACTION_TIERS as readonly string[]).includes(t);
}
if (!isTier(tier)) tier = normalizeTier(tier); Type guard
function isTier(t: string): t is ExtractionTier {
return (EXTRACTION_TIERS as readonly string[]).includes(t);
} Try / catch
try {
diag.recordAttempt(tier);
} catch (e) {
if (e instanceof Error && e.message.startsWith("unknown extraction tier")) {
logger.warn("dropping diagnostics for unknown tier", { tier });
} else throw e;
} Prevention
- Type tier variables as ExtractionTier end-to-end so bad strings fail at compile time.
- Derive tier labels from the EXTRACTION_TIERS constant, never string literals.
- When renaming a tier, add a mapping for persisted historical labels.
When it happens
Trigger: Calling recordAttempt/recordSuccess/recordNoOutput/recordFailure with a hand-written tier string that is misspelled, differently cased, or from a newer tier list than the running build supports.
Common situations: Custom pipelines logging diagnostics with their own tier names, typos like "fastt"/"Deep", or persisting old tier labels that no longer exist after an upgrade.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unknown recall tier ${JSON.stringify(tier)}; valid tiers: ${
- Unsupported language '{value}'. Supported: {}
- litterbox option ttl must be one of 1h, 12h, 24h, or 72h
- Invalid value: ${rawValue}. Valid values: ${valid.join(", ")
- Invalid --source: ${args.source}. Expected one of: ${TTSR_SO
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/3c8f2ed7ad61f534.
Report an issue: GitHub.