Visitar URL original
fix(cli): a --questions path that cannot be read is a usage error naming the file by PerryLink · Pull Request #1397 · NandhaKishorM/laya · GitHub
Skip to content

fix(cli): a --questions path that cannot be read is a usage error naming the file - #1397

Merged
NandhaKishorM merged 1 commit into
NandhaKishorM:mainfrom
PerryLink:fix/questions-file-cannot-be-read
Oct 28, 2026
Merged

NandhaKishorM merged 1 commit into
NandhaKishorM:mainfrom
PerryLink:fix/questions-file-cannot-be-read

Conversation

@PerryLink

Copy link
Copy Markdown
Contributor

A --questions path that exists but cannot be opened as a file is reported as a runtime failure instead of a usage error about that file.

What happens

$ laya --questions /tmp "hi"
laya: could not run Laya ([Errno 21] Is a directory: '/tmp').
Check that the dependencies are installed and the checkpoints can be downloaded from the Hugging Face hub (network access is needed on first use).

Exit 2 either way, but the diagnosis is wrong: nothing is missing and nothing was downloaded. The same happens for a file this process may not read (EACCES).

Why

load_questions converts the four neighbouring faults into a ValueError naming the path — missing file, invalid JSON, non-UTF-8 text, JSON nested past the reader — but an OSError from open() itself escaped to run(), whose except (ImportError, OSError, RuntimeError) is the dependency/checkpoint handler. laya/evidence.py::_read_json_object and laya/evals.py::Dataset.from_jsonl already treat an unreadable path as the caller's mistake about a named file; the --batch path does too (could not read FILE (err)). This is the last one that did not.

Change

One except OSError after the FileNotFoundError arm, raising --questions file <path> cannot be read: <errno text>. FileNotFoundError keeps its own message. No library behaviour changes; run() already turns a ValueError into exit 2.

Tests

tests/test_cli.py gains one case: --questions pointing at a directory must exit 2, name the path, and not say "could not run Laya", and must never reach predict.

  • without the change: 209 passed, 1 failed — the new check reports the could not run Laya message above;
  • with the change: 210 passed, 0 failed, all CLI tests passed.

Run as PYTHONPATH=<deps>:<repo> python3 tests/test_cli.py (the suite stubs the Router, so no weights are loaded).

…ing the file

`load_questions` turns a missing file, invalid JSON, a non-UTF-8 file and too-deep JSON
into a ValueError naming the path, but a path that exists and cannot be opened as a file --
a directory, or a file this process may not read -- still raised the raw OSError. `run()`
catches OSError in its runtime handler, so the caller was told "could not run Laya" and
advised to check the network and the checkpoints: a false diagnosis for a wrong
--questions argument.

The neighbouring refusals in this function, `laya/evidence.py::_read_json_object` and
`laya/evals.py::Dataset.from_jsonl`, already name the path; this makes the remaining one
agree with them. The --batch path already reports "could not read FILE (err)".
@NandhaKishorM
NandhaKishorM merged commit eeea2fd into NandhaKishorM:main Oct 28, 2026
52 checks passed
NandhaKishorM added a commit that referenced this pull request Oct 28, 2026
24 PRs. Vietnamese kept off the English checkpoint (#1392), deciding-window
attribution preserved through end hooks (#1369), RemoteRouter identifying
itself with a configurable User-Agent (#1396), ten more inputs refused where
they enter (#1372, #1394, #1397, #1398, #1400, #1401, #1402, #1403, #1404,
#1405, #1406), per-language temperatures and per-call budgets in .NET and
Rust (#1370, #1371), .NET calibration files (#1384), the Go router lifecycle,
SHA-256 pins and routed inference (#1374, #1379, #1395), a C++ foundation
(#1399, #1407), and parity-lane sharding that replaces the budget headroom
added for 0.4.16 (#1373, #1375).

Verified before tagging: all 92 suites pass, 640 tests, up from 612. ruff
clean on both lists. laya-ts 1251 tests across 44 files, tsc --noEmit clean.
Every generated-artifact gate clean on CPython 3.12 / unicodedata 15.0.0:
Java 20 families match laya (9 unverified), UnicodeTables matches CPython
15.0.0, LanguageTables matches laya/lang.py, three Go tables_gen.go match,
both laya-cpp .inc files match. Version agrees across pyproject.toml,
laya.__version__ and nix/package.nix. README carries 0.4.17 only.

Security audit of the merge diff, 362766 added lines over 480 files: zero
obfuscation, zero secrets, zero boundary hits, zero binaries, no mode or
symlink changes, 20 of 20 actions SHA-pinned including the new cpp.yml, npm
install hooks unchanged, and no third-party host in any added line
(example.com 90, github.com 2, download.pytorch.org 1, docs.rs 1). The 12
dynamic-exec hits are the C++ test harness invoking its own checker through
sys.executable, the Go sample generator reading laya's own example by AST at
development time, and one comment in rust.yml.

Held: #1364 (unchanged, it moves a cross-port contract), #1381 (a #[doc(hidden)]
but pub Rust hook that would ship as public API able to replace the forward
pass), #1386 (route_batch switched from self.route to self._route, silently
bypassing subclass overrides the docstring promises), and nine stacked port
PRs that conflict with each other and need linearizing (#1377, #1378, #1380,
#1382, #1383, #1385, #1387, #1388, #1389, #1390).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@NandhaKishorM

Copy link
Copy Markdown
Owner

Merged. A --questions path that cannot be read is a usage error and naming the file in it is the whole point, since the alternative is a traceback that makes the user guess which of several paths on the command line was wrong.

A note on the merge, because it affected your patch. This landed in the same release as #1398, and both add a block to the same region of tests/test_cli.py. Git saw an add/add conflict rather than something it could compose, so I resolved it by keeping both blocks in order: your directory case first, then the BOM case. Nothing was dropped and the file reports 213 passed. If you pull main and your local branch looks like it lost something, that resolution is why.

Shipped in 0.4.17.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants