Closed general

pkg update: degrade per-package on dependency conflicts instead of failing the whole sweep

Drew Owens · 3mo ago ·closed by Colby Knox

When the resolver hits a dependency version conflict, the entire pkg update sweep fails - so one package's stale range stops EVERY package on the container from updating, fleet-wide (this is the auto-update path adom-hook runs, so it fails silently in the background and packages rot until someone investigates).

Today's example: adom/[email protected] pinned adom/adom-google@^0.7.0 after adom-google moved to 0.8.x; every container's sweep died with 'Dependency version conflict: cannot satisfy adom/adom-google@^0.8.3 and adom/adom-google@latest and adom/adom-google@^0.7.0 simultaneously'.

The sweep already degrades gracefully for other failure classes - SCRIPT_FAILED and STALE_INSTALL warn and continue ('skipped; the rest of the update continued'). Conflicts deserve the same treatment. Options, roughly in order of preference:

  • Resolve to the newest version that satisfies the majority of constraints, warn loudly about the packages whose ranges were overridden, and continue.
  • Or: skip updating only the packages involved in the conflict (leave them at their installed versions), warn with the exact conflicting ranges and which package declares each, and continue updating everything else.

Either way the warning should name the DECLARING package for each conflicting range (today's error names the ranges but not who declares ^0.7.0 - finding the culprit required grepping package.json files by hand).

1 Reply

Colby Knox · 3mo ago

Fixed in adom-wiki-cli 1.0.56 (5/5 platforms, latest).

pkg update now degrades per-package on dependency conflicts, exactly like it already did for missing packages (STALE_INSTALL) and script failures (SCRIPT_FAILED). The resolve runs in a loop: on a conflict, the DECLARING packages are left at their installed versions, a CONFLICT_SKIPPED warning fires, and the rest of the sweep continues -- the contested dep then resolves against the remaining constraints (your option A for the dep, option B for the declarers). Capped at 4 degrade rounds. install/add/ci stay strict, matching the existing precedent.

Your "name the DECLARING package" ask is in, both modes: the declarers and the exact range each declares are read from installed-state dependencies, so CONFLICT_SKIPPED says e.g. "adom/wiki-notify-gchat (declares ^0.7.0), adom/adom-google-adom (declares ^0.8.3)" -- no more grepping package.json by hand. Strict-mode failures carry the same names as CONFLICT_DECLARER hints.

Verification, honestly stated: the server's structured conflicts[] payload ({slug, chosen, conflictSpec, allSpecs}) was confirmed live by recreating incident 1's constraint set with a read-only resolve (adom-google@^0.7.0 + adom-google-adom@*), and the declarer lookup and range logic are unit-tested -- but a true end-to-end wedge is no longer constructible on prod since wiki-notify-gchat 1.6.5 fixed its range, so the degrade loop has not been exercised against a live fleet wedge. If another one appears before the fleet drains onto 1.0.56, its hook logs will be the real-world test.

Companion: the publish-time prevention half is #13 (STALE_RANGE lint, also in 1.0.56).

Log in to reply.