#1474·magika

js: Status enum values use kebab-case, diverging from the Python reference (file_not_found_error / permission_error)

Author: kaluli123123Created Sep 14, 2026Updated Sep 14, 2026

Summary

The JS/TS Status enum uses kebab-case string values ("file-not-found-error", "permission-error"), while the reference Python implementation — and the two sibling enums in the very same js/src/ directory — use snake_case ("file_not_found_error", "permission_error"). Any consumer that compares or serializes MagikaResult.status across implementations gets a mismatch.

Environment

  • main @ e6a4c8e ("Expose the Rust library as a C library (#1449)")
  • js/ package magika (TypeScript source), Node 22

Evidence

js/src/status.ts:15-27:

typescript
export enum Status {
  OK = "ok",
  FILE_NOT_FOUND_ERROR = "file-not-found-error",
  PERMISSION_ERROR = "permission-error",
  UNKNOWN = "unknown",
}

Reference — python/src/magika/types/status.py is a LowerCaseStrEnum over enum.auto(), and python/src/magika/types/strenum.py generates name.lower(), so the canonical values are snake_case. This is pinned by python/tests/test_magika_python_module.py:992-995:

python
assert Status.OK.value == "ok"
assert Status.FILE_NOT_FOUND_ERROR.value == "file_not_found_error"
assert Status.PERMISSION_ERROR.value == "permission_error"
assert Status.UNKNOWN.value == "unknown"

The two sibling enums in js/src/ were transcribed correctly, which establishes the intended convention and rules out a deliberate JS-side kebab-case choice:

typescript
// js/src/prediction-mode.ts
BEST_GUESS = "best_guess", MEDIUM_CONFIDENCE = "medium_confidence", HIGH_CONFIDENCE = "high_confidence"

// js/src/overwrite-reason.ts
NONE = "none", LOW_CONFIDENCE = "low_confidence", OVERWRITE_MAP = "overwrite_map"

Reproduction

bash
cd js
node -e 'const s=require("ts-node")' 2>/dev/null
npx tsc --noEmit  # (or simply read src/status.ts)
typescript
import { Status } from "./src/status";
console.log(Status.FILE_NOT_FOUND_ERROR); // "file-not-found-error"
console.log(Status.PERMISSION_ERROR);     // "permission-error"

Actual vs expected

member JS actual Python reference / expected
OK ok ok
FILE_NOT_FOUND_ERROR file-not-found-error file_not_found_error
PERMISSION_ERROR permission-error permission_error
UNKNOWN unknown unknown

Impact

  1. Cross-implementation consumers break. A JS caller that follows the documented vocabulary and writes if (result.status === "permission_error") never matches.
  2. It is latently load-bearing inside the repo. js/test/inference-vs-reference.test.ts:76,109 asserts expect(result.status).toBe(exampleByPath.status) against the shared, Python-generated artifacts tests_data/reference/standard_v3_3-inference_examples_by_{path,content}.json.gz. I decompressed both: all 207 + 141 examples currently have status == "ok", which is the only reason the JS suite is green today. The day a reference example with a non-ok status is added, the JS reference test fails for a reason that has nothing to do with the change being made.

Root cause

The hand-written TS mirror of Python's Status enum was transcribed with hyphens instead of the name.lower() snake_case that LowerCaseStrEnum generates.

Proposed fix

Two string literals in js/src/status.ts:

typescript
FILE_NOT_FOUND_ERROR = "file_not_found_error",
PERMISSION_ERROR = "permission_error",

No call site needs touching — a repo-wide search shows the only producers/consumers reference the enum members, never the literals.

Note this does change the serialized value for JS consumers who (incorrectly) depend on the hyphenated form; the alternative is for Python/Rust/the reference artifacts to move to hyphens, which would be a far larger break. Happy to follow maintainer preference here.

I have the fix plus a regression test mirroring the Python assertions and will open a PR shortly.