Skip to content

Report the exit code the engine actually saw - #17

Merged
MickLesk merged 6 commits into
mainfrom
fix/telemetry-exit-codes
Sep 1, 2026
Merged

Report the exit code the engine actually saw#17
MickLesk merged 6 commits into
mainfrom
fix/telemetry-exit-codes

Conversation

@MickLesk

@MickLesk MickLesk commented Sep 1, 2026

Copy link
Copy Markdown
Member

✍️ Description

Four places turned real information into "exit code 1, category shell",
which is why that pair sat at the top of the dashboard telling nobody
anything.

  • post_update_to_api defaulted its code argument to 1 and mapped
    anything non-numeric to 1. "No code was passed" and "the command
    returned 1" became the same number — and 1 is what bash returns for any
    ordinary failure. Both now report 199, a new code meaning exactly that.
  • The host read the container's code with cat flag || echo "1", throwing
    away lxc-attach's own return value taken a few lines earlier. It falls
    back to that instead.
  • 113, 114, 122, 253 and 254 are the engine asking a question and being
    told no. Filing them as failures is why exit 113 was one of the
    largest signatures in the data. They now report aborted, and
    categorize_error agrees.
  • community-scripts/core no longer lands in the fork branch. Runs
    bootstrapped without COMMUNITY_SCRIPTS_URL scrape the bootstrap line,
    which names only the engine — that gave the slug its own dashboard row
    (4,451 runs, second to ProxmoxVE) as REPO_SOURCE=external.

199 is in both copies of the table, including the container fallback in
core/error_handler.func.

Verified with bash -n on all five files and functionally against the
real functions: failed 113 → aborted/113, failed 1 → failed/1,
failed <no code> → failed/199, core → ProxmoxVED, real fork still
external. shellcheck runs in CI.

🔗 Related Issue

Fixes #

✅ Prerequisites (X in brackets)

  • Self-review completed – Code follows project standards.
  • Tested thoroughly – Changes work as expected (Proxmox VE and/or Incus, as applicable).
  • No security risks – No hardcoded secrets, unnecessary privilege escalations, or permission issues.
  • API.txt regenerated – If a function signature or behavior changed, API.txt was updated to match.

🤖 AI Assistance (X in brackets)

If you used an AI tool (GitHub Copilot, Claude, ChatGPT, etc.) to write or generate any code in this PR, you must confirm compliance below.
Select exactly one option.

  • No AI used – Code was written without AI assistance.
  • AI was used – The output has been reviewed and corrected, and I take responsibility for it matching this repo's conventions.

🛠️ Type of Change (X in brackets)

  • 🐞 Bug fix – Resolves an issue without breaking functionality.
  • New feature – Adds new, non-breaking functionality.
  • 💥 Breaking change – Alters existing behavior in a way that may require updates in every downstream script.
  • 🔧 Refactoring / Code Cleanup – Improves readability or maintainability without changing functionality.
  • 📝 Documentation update – Changes to README, docs/, CONTRIBUTING.md, or other docs.
Four places were turning real information into "exit code 1, category
shell", which is why that pair sat at the top of the dashboard while
telling nobody anything.

post_update_to_api defaulted its code argument to 1 and mapped anything
non-numeric to 1. Both mean "no code was passed", which is not the same
fact as "the command returned 1" -- and 1 is what bash returns for every
ordinary failure, so the two were indistinguishable once written. They
now report 199, which says what happened.

The host read the container's code with `cat flag || echo "1"`, throwing
away a code it already had: lxc-attach's own return value, taken a few
lines earlier. It falls back to that now.

Codes 113, 114, 122, 253 and 254 are the engine asking a question and
being told no. They were filed as failures, so "exit 113" -- a user
declining an under-provisioned update -- was one of the largest single
signatures in the data, sitting under exit code 1. They join the signal
codes in reporting "aborted", and categorize_error agrees with that
branch so a run is not filed as one thing and described as another.

199 is added to both copies of the table: api/exitcodes.func and the
fallback in core/error_handler.func that containers use when api.func is
not loaded. The header pointed at docs/exit_codes.md for keeping them in
step, which does not exist; it now names what actually has to move.
Runs bootstrapped without COMMUNITY_SCRIPTS_URL fall through to scraping
/proc/$$/cmdline, and the bootstrap line names only the engine. So the
scrape finds "community-scripts/core", which matched no known repo and
landed in the fork branch: REPO_SOURCE=external, REPO_SLUG=
community-scripts/core.

That is not a fork. It gave the slug its own row on the dashboard --
4,451 runs, second only to ProxmoxVE itself -- and counted every one of
them as somebody else's code. core now joins the empty case and takes
the hardcoded fallback, which CI rewrites from VED to VE on promotion.

Method 0 already existed to prevent this and is untouched; these are the
runs where it does not apply.
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Try this branch

The engine and the scripts resolve independently, so a production script can
be run against the engine from this PR by setting one variable:

COMMUNITY_SCRIPTS_CORE_URL=https://raw.githubusercontent.com/community-scripts/core/fix/telemetry-exit-codes \
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/debian.sh)"

Swap ct/debian.sh for whatever exercises the change.

This PR touches pve/, so it needs a Proxmox VE host.

Run a script from a fork as well
curl -fsSL https://raw.githubusercontent.com/community-scripts/core/fix/telemetry-exit-codes/tools/run.sh |
  bash -s -- https://raw.githubusercontent.com/YOU/ProxmoxVED/your-branch ct/debian.sh \
             https://raw.githubusercontent.com/community-scripts/core/fix/telemetry-exit-codes

Note that run.sh is reached through a pipe, so the script it starts inherits
an exhausted stdin. Whiptail is fine — it opens /dev/tty — but a plain read
would see EOF. The single-variable form above does not have that problem.

Useful flags while testing

dev_mode=net logs every engine fetch with status and duration, which is the
quickest way to confirm the branch is really being used. dev_mode=keep stops a
failed build from deleting the container along with the evidence.

post_update_to_api defaulted its code argument to 1 and mapped anything
non-numeric to 1, so "no code was passed" and "the command returned 1"
became the same number -- and 1 is what bash returns for any ordinary
failure. Both now report 199.

The host read the container's code with `cat flag || echo "1"`, throwing
away lxc-attach's own return value taken a few lines earlier. It falls
back to that instead.

113, 114, 122, 253 and 254 are the engine asking a question and being
told no. Filing them as failures is why "exit 113" was one of the
largest signatures in the data, sitting under exit code 1. They now
report aborted, and categorize_error agrees.

199 is added to both copies of the table, including the container
fallback in core/error_handler.func.
Runs bootstrapped without COMMUNITY_SCRIPTS_URL fall through to scraping
/proc/$$/cmdline, where the bootstrap line names only the engine. The
scrape finds "community-scripts/core", which matched no known repo and
landed in the fork branch as REPO_SOURCE=external.

That gave the slug its own row on the dashboard -- 4,451 runs, second
only to ProxmoxVE -- and counted them all as somebody else's code. core
now joins the empty case and takes the hardcoded fallback, which CI
rewrites from VED to VE on promotion.
It arrived in lib/runtime.func with #16 and the snapshot was not
regenerated, so "Each loader still defines its whole API" fails on main
and on every branch opened from it.
@MickLesk
MickLesk merged commit 75d006e into main Sep 1, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant