Skip to content

app validate on a path that does not exist reports a missing manifest and exits 1 — the contract says 2 #256

Description

@ZacxDev

Found by a blind dogfood run against v0.1.90-21-gf56aa72.

Symptom

A path that does not exist is reported as "a project root without a manifest", and exits 1 where the published contract says 2.

$ civitai app validate /nope/does/not/exist ; echo $?
✗ 1 validation error(s) in /nope/does/not/exist:
  - block.manifest.json not found at project root /nope/does/not/exist
Error: validation failed
1

Two problems in one line:

  1. Wrong diagnosis. "not found at project root X" states that X is a project root and merely lacks a manifest. The truth is that X is not there at all. A first-time author reads this and starts hunting for a typo in the filename rather than in the path.
  2. Wrong exit code. The exit-code contract published from exitCodeDocs draws the split explicitly for a named local path that is not there: it exits 2 (a mistake about the invocation), not 1.

A file that is not a directory is worse — a raw syscall error with a concatenated nonsense path:

$ civitai app validate ./README.md ; echo $?
Error: stat README.md/block.manifest.json: not a directory
1

This is the third copy of an inconsistency already fixed twice

The identical mistake, two commands, after #251:

$ civitai generate --input /nope/x.json --print-input
Error: --input /nope/x.json: no such file — pass a path that exists, or `--input -` to read
the graph from stdin; produce a starting point with `civitai generate "a cat" --print-input`
rc=2

$ civitai app validate /nope
- block.manifest.json not found at project root /nope
rc=1

Same class of error, same user mistake. One names the fix and exits 2; the other is bare and exits 1. #242, #245 and #251 each closed one copy of "a path failure is sorted by the wrong axis"; this is the remaining one, and it sits on the command a new author runs most.

AGENTS.md item 24 is the governing context — the split is by the author's mistake, not by the errno.

Suggested fix

In app validate's path resolution, os.Stat the target before looking for the manifest and branch three ways:

  • does not existasUsageError (exit 2), message naming the next command (civitai app create, or civitai app validate <dir> if they meant a different directory);
  • exists but is not a directoryasUsageError (exit 2), saying so plainly rather than surfacing stat X/block.manifest.json: not a directory;
  • is a directory with no manifest → the current message and behaviour, which are correct.

Keep the "directory with no manifest" case as-is: it is a genuine validation finding, not a usage error.

Test coverage this needs

Pin the exit code with errors.Is(err, ErrUsage), never message text — per AGENTS.md item 7, the sentinels carry no visible text, so a message assertion says nothing about the code. Measured on #251: an equivalent one-token mutation passed a green suite because every existing assertion was on wording.

Rows: missing path → 2; a regular file → 2; a real project dir with no manifest → 1 (control, unchanged); a valid project → 0 (control).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions