Skip to content

fix(cli): surface compose-flags resolver failures instead of silencing them#1925

Open
w3-surfer wants to merge 1 commit into
Osmantic:mainfrom
w3-surfer:fix/compose-flags-surface-resolver-error
Open

fix(cli): surface compose-flags resolver failures instead of silencing them#1925
w3-surfer wants to merge 1 commit into
Osmantic:mainfrom
w3-surfer:fix/compose-flags-surface-resolver-error

Conversation

@w3-surfer

Copy link
Copy Markdown
Contributor

Fixes #1876.

Problem

_regenerate_compose_flags in ods-cli ran the resolver with stderr discarded, and removed the cache on failure:

"$INSTALL_DIR/scripts/resolve-compose-stack.sh" \
    ... \
    > "$INSTALL_DIR/.compose-flags" 2>/dev/null || rm -f "$INSTALL_DIR/.compose-flags"

resolve-compose-stack.sh already prints an actionable diagnosis when it can't run:

ERROR: PyYAML is required by resolve-compose-stack.sh for compose validation.
       Or install manually: <python> -m pip install pyyaml

but 2>/dev/null threw it away. As reported in the issue, ods enable <ext> then appeared to succeed and the real failure only surfaced two commands later as compose's no configuration file provided: not found, with no hint of the cause.

Fix

Capture the resolver's stderr and print it after a warning that names the consequence, so the failure is reported where it happens:

local resolver_err=""
if ! resolver_err=$("$INSTALL_DIR/scripts/resolve-compose-stack.sh" \
    ... \
    2>&1 > "$INSTALL_DIR/.compose-flags"); then
    rm -f "$INSTALL_DIR/.compose-flags"
    warn "Could not regenerate the compose stack cache. 'ods start' will fail until this is resolved:"
    [[ -n "$resolver_err" ]] && printf '%s\n' "$resolver_err" >&2
fi

The 2>&1 > file ordering keeps stdout going to .compose-flags and captures only stderr, so successful runs behave exactly as before.

Also corrected the lib/service-registry.sh warning, which said only "Service registry will be incomplete" while lifecycle commands actually break. It now states that ods enable / ods start will fail.

Verification

Extracted the real function and ran it against a stub resolver covering both paths:

Resolver fails (stub reproduces the PyYAML error):

WARN: Could not regenerate the compose stack cache. 'ods start' will fail until this is resolved:
ERROR: PyYAML is required by resolve-compose-stack.sh for compose validation.
       Or install manually: python3 -m pip install pyyaml
.compose-flags removed

Resolver succeeds: stderr empty, .compose-flags contains -f docker-compose.base.yml -f docker-compose.nvidia.yml.

bash -n passes on both files.

Out of scope

The issue also suggests a host-Python PyYAML preflight check on the macOS install path. That is a larger, separate change and is not included here.

…g them

_regenerate_compose_flags ran resolve-compose-stack.sh with 2>/dev/null and
deleted .compose-flags on failure. The resolver already prints an actionable
diagnosis (for example "ERROR: PyYAML is required ..." plus the install
command), but the CLI discarded it, so the real failure only surfaced two
commands later as compose's "no configuration file provided: not found"
with no hint of the cause.

Capture the resolver's stderr and print it after a warning that names the
consequence, so `ods enable` reports why `ods start` is about to fail.
Successful runs are unchanged: stdout still goes to .compose-flags and
nothing is printed.

Also correct the service-registry warning, which said only "Service
registry will be incomplete" while lifecycle commands actually break.

Fixes Osmantic#1876

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@w3-surfer

Copy link
Copy Markdown
Contributor Author

@nolanmak thanks for the precise diagnosis here, it made this a quick fix. If you were already planning to take it yourself, say the word and I'll close this in favor of yours.

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.

ods-cli: compose-flags regeneration fails silently without PyYAML, breaking 'ods start <ext>'

1 participant