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

  1. Use only tier names from EXTRACTION_TIERS (import the constant and iterate it instead of hardcoding).
  2. Type the tier parameter as ExtractionTier so invalid strings fail at compile time.
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/3c8f2ed7ad61f534. Report an issue: GitHub.