-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting and FAQ
Start by separating command failure from analysis outcome:
- Exit code
1or2: no valid report was produced; fix the invocation or environment. - Exit code
0: a valid report exists; inspectresolution.statusand the other report dimensions. -
resolution.status: blocked: Composer evidence found a target conflict; the command still correctly returns 0. -
resolution.status: unknown: evidence was insufficient or an operational problem prevented a reliable solver conclusion.
Run the executable installed by Composer:
vendor/bin/upgrade-intel --helpvendor\bin\upgrade-intel.bat --helpFor a source checkout, run composer install at the repository root first. Do not copy the PHP executable by itself; it depends on Composer autoloading.
Use the project-relative launcher instead of expecting a global command.
./vendor/bin/upgrade-intel --help.\vendor\bin\upgrade-intel.bat --helpConfirm you are in the Composer project where the CLI package is installed.
The analyzer launches composer from PATH unless --composer-executable selects another command.
composer --version
which composercomposer --version
Get-Command composerExternal analysis needs Composer in the tools environment, not inside the target application.
Do not install the analyzer into that application. Install CLI and adapter in a separate directory running PHP 8.0+:
mkdir php-upgrade-tools && cd php-upgrade-tools
composer require php-upgrade-preflight/cli:^0.3 php-upgrade-preflight/laravel:^0.3
vendor/bin/upgrade-intel analyze \
--path=/work/php74-app \
--from-php=7.4 \
--target-php=8.1 \
--target=laravel/framework:^9.0 \
--framework=laravelNew-Item -ItemType Directory php-upgrade-tools | Out-Null
Set-Location php-upgrade-tools
composer require php-upgrade-preflight/cli:^0.3 php-upgrade-preflight/laravel:^0.3
vendor\bin\upgrade-intel.bat analyze `
--path=C:\work\php74-app `
--from-php=7.4 `
--target-php=8.1 `
--target=laravel/framework:^9.0 `
--framework=laravelThe PHP 8 analyzer can model PHP 7.4 as the source state. It does not boot the target.
Host installability and analyzed target scope are separate. Project-local adapter installation requires Laravel 8–13 and the applicable host PHP floor. External CLI analysis installs the adapter in its own PHP 8 tools project, then reads Laravel 7 metadata and source without booting Laravel 7.
Use explicit options for automation:
vendor/bin/upgrade-intel analyze --target-php=8.2Use the guided flow only in a real terminal:
vendor/bin/upgrade-intel wizardThe Artisan command is different:
php artisan upgrade:analyze --target-php=8.2The wizard requires both terminal-attached stdin and a visible terminal on stderr. It intentionally rejects pipes, redirected prompt streams, CI sessions, and other non-TTY contexts instead of silently accepting defaults. Use the equivalent upgrade-intel analyze --name=value command in automation.
End-of-input returns code 2. Entering cancel, quit, or q returns 130; no analysis starts in either case.
unverified means the package lookup could not prove the answer. Common causes are an empty local cache, disabled or unavailable network, authentication failure, timeout, malformed Composer metadata, or restricted execution without an isolated lookup state. It is not evidence that the package does not exist.
Choose composer.json only to avoid an external lookup, retry with the configured project repositories if their network and credential boundary is acceptable, or continue and let the actual analysis scenarios produce report evidence. An explicit not_found is reserved for a clear response from the configured repository universe; no_matching_version means the package was found but the chosen constraint matched none of its discovered versions.
Progress is printed only when stderr is attached to a terminal. It is deliberately suppressed when stderr is redirected or piped, while stdout remains the canonical report stream. Both upgrade-intel analyze and php artisan upgrade:analyze use durable phase lines rather than an animated spinner.
Standalone values must use =:
# Wrong
vendor/bin/upgrade-intel analyze --path /work/app --target-php 8.2
# Right
vendor/bin/upgrade-intel analyze --path=/work/app --target-php=8.2PowerShell:
vendor\bin\upgrade-intel.bat analyze --path=C:\work\app --target-php=8.2Supply at least one of:
--target=vendor/package:constraint
--target-php=exact-version
--target-platform-profile=path
A profile containing exact PHP may provide the PHP target without a separate switch.
PHP simulation uses an exact value, not a Composer range.
# Accepted
--target-php=8.3
--target-php=8.3.4
# Rejected
--target-php=^8.3
--target-php='>=8.2'If --target=php:8.3 and --target-php=8.2 appear together, they conflict and invocation returns code 2.
Use vendor/package:constraint with a valid Composer package name and constraint:
--target=laravel/framework:^11.0Avoid spaces that the shell can split. Quote the entire token if your shell requires it.
Install the adapter beside the CLI:
composer require php-upgrade-preflight/laravel:^0.3
composer show php-upgrade-preflight/laravelAn explicit unavailable --framework=laravel is invalid input and returns code 2. An unrelated malformed adapter manifest may also emit a discovery diagnostic on stderr.
Check that the package is installed and package discovery is working:
composer show php-upgrade-preflight/laravel
php artisan package:discover
php artisan listcomposer show php-upgrade-preflight/laravel
php artisan package:discover
php artisan list | Select-String upgradeThe service provider registers the command only when the application runs in console mode. If Laravel cannot boot, use the external CLI.
Run:
php artisan --versionIf that fails, an application/provider/configuration problem prevents every Artisan command, including preflight. External CLI analysis does not boot the application and is the safer fallback.
Read transition.framework_guidance[].uncertainties.
-
supported: every required hop has a rule pack. -
partially_supported: a covered prefix exists, then guidance stops at a gap. -
unsupported: no safe first hop/path can be selected.
Common causes are an ambiguous source/target major, same-major request, downgrade, target outside Laravel 7–13, or missing required hop. Do not use resolution.status to override guidance coverage; Composer feasibility and rule coverage answer different questions.
Inspect:
staged_resolution.execution_state
staged_resolution.status
staged_resolution.stop_reason
staged_resolution.evidence
Staging may skip because no adapter supplies targets, providers conflict, endpoints are ambiguous, an adjacent hop is missing, the request exceeds a budget, or no exact request-backed PHP value satisfies adapter metadata.
A skipped stage is not a Composer blocker. Direct resolution and framework guidance remain independently useful.
This is expected.
process exit code 0 = report production succeeded
resolution.status blocked = Composer final-target evidence found blockers
CI should first require exit code 0, then parse JSON:
vendor/bin/upgrade-intel analyze --path=/work/app --target-php=8.2 --output=/work/reports/app.json
test "$?" -eq 0 || exit $?
status="$(jq -r '.resolution.status' /work/reports/app.json)"
test "$status" = feasible -o "$status" = feasible_with_changesvendor\bin\upgrade-intel.bat analyze --path=C:\work\app --target-php=8.2 --output=C:\work\reports\app.json
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$status = (Get-Content -Raw C:\work\reports\app.json | ConvertFrom-Json).resolution.status
if ($status -notin @('feasible', 'feasible_with_changes')) { exit 10 }Exit 10 in the wrapper is your policy, not an analyzer exit code.
Unknown is an honest evidence limit. Inspect scenario outcome, diagnostics, Composer execution provenance, and uncertainties.
Typical causes:
- Composer executable missing or outside the expected range;
- timeout;
- restricted cache lacks repository metadata;
- complete profile used with Composer 2.0/2.1;
- baseline validation failure;
- operational workspace problem;
- redaction or parsing prevented confident classification.
Fix the cause and rerun. Do not translate unknown into feasible or blocked.
Check composer --version. Complete closed-world simulation needs Composer 2.2+ because older versions cannot hide all unlisted supported platform packages.
Also check for:
- contradictory target PHP between request and profile;
- contradictory extension values;
- presence-only extension assumptions combined with completeness;
- unsupported names or non-exact versions;
- malformed JSON or unsupported schema/completeness.
The analyzer does not silently downgrade complete to partial.
Compare these inputs first:
- Composer version and expected range;
- compatible versus restricted mode;
- repository metadata and credentials;
- target profile digest and completeness;
- explicit extension assumptions;
- unlisted host platform packages;
- original
config.platform; - path repository content.
Stable markers normalize common absolute roots, but Composer-produced lock metadata, durations, and raw lock hashes can vary. A partial platform request is deliberately host-dependent.
--output and --save-report destinations must be outside the analyzed project. Their parent must already exist and be writable, and the destination must not be a directory. The two options cannot be combined: --output is file-only delivery, while --save-report preserves stdout and adds an identical file copy.
mkdir -p /work/reports
vendor/bin/upgrade-intel analyze --path=/work/app --target-php=8.2 --output=/work/reports/app.jsonNew-Item -ItemType Directory -Force C:\work\reports | Out-Null
vendor\bin\upgrade-intel.bat analyze --path=C:\work\app --target-php=8.2 --output=C:\work\reports\app.jsonAvoid stdout redirection into the project because the shell creates the file before analyzer validation.
Every --source must exist and resolve inside --path. Relative values are project-relative.
--path=/work/app --source=app --source=tests/FeatureDo not pass a sibling shared library as --source; analyze it as its own Composer project or include it through the project's supported layout.
Ordinary relative path repository URLs are resolved against the target before Composer runs. URLs containing environment variables or ~ remain untouched. Use an absolute URL or define the variable in the analyzer process.
Shareable reports replace the resolved root with [LOCAL_REPOSITORY].
Compatible mode can use the analyzer host's normal authentication and network. Configure scoped credentials in the tools environment.
Restricted mode intentionally starts with empty Composer state and requests offline behavior. A metadata miss becomes repository_metadata_unavailable; it is not a package incompatibility.
If a credential appears unredacted, stop sharing, rotate it, and report only a synthetic reproduction through the private security channel.
Default scenario timeout is 300 seconds; diagnostic timeout is 60 seconds.
--composer-timeout=600 --composer-diagnostic-timeout=90Check repository availability, credentials, proxy behavior, and noninteractive authentication. Increase timeouts only after confirming the process is making legitimate progress.
Default reports expose only [ANALYZER_WORKSPACE] and record cleanup_failure. If authorized, rerun with --debug to reveal and retain the exact path for diagnosis.
Do not share the debug report or retained workspace. Remove it manually after its value has been consumed, according to local retention policy.
--with-extension=ext-json proves only modeled presence through a sentinel. It cannot prove a real version satisfies a versioned constraint. Supply an exact value such as --with-extension=ext-json:8.3.0 when verified, or use a platform profile.
Composer success proves one dependency solution was found under the recorded inputs. It does not prove:
- the application boots;
- framework migrations were applied;
- tests pass;
- extensions behave as expected;
- database or external service compatibility;
- deployment configuration matches the model.
Use tests, framework_findings, source_impact, and uncertainties to plan the real validation.
source_inventory records observed declarations/usages. source_impact includes only observations correlated with a selected package change or applicable framework rule. Dynamic or unowned usages can remain inventory-only.
No impact is not a clean-runtime guarantee. Static scanning does not evaluate dynamic class names, container bindings, generated code, or application execution.
Dispatch on metadata.schema_version. v0.3.x writes 0.8, which adds required top-level composer_execution and staged_resolution, required request Composer policy, and nullable platform-profile fields.
Do not treat an absent old-schema field as equivalent to a present schema 0.8 null. Update the consumer using the ordered schema migration documentation.
No. It says Composer found a candidate dependency state with package changes. Engineering must review the diff, apply changes in a branch, run tests on the target runtime, and validate deployment.
Yes, but compare recorded Composer execution and platform provenance first. A complete verified profile narrows platform differences; it does not pin repositories, credentials, network, or Composer behavior.
It reports a bounded estimate with confidence and assumptions. Use it for planning discussion, not as a fixed quote or schedule commitment.
No. It hardens Composer-layer state and requests offline behavior, but it is not process or network isolation. Use an external disposable sandbox.
Share Markdown for human review and retain JSON as canonical evidence. Review either artifact for sensitive data before distribution.
- package version and
metadata.tool_versionif a report exists; -
metadata.schema_version; - operating system and PHP version;
- Composer version and selected execution mode;
- sanitized command with secrets and private paths removed;
- process exit code;
- relevant scenario
outcome, not only its numeric Composer exit code; - expected versus actual behavior;
- a synthetic reproducer when possible.
Never attach a retained debug workspace from a private project.
PHP Upgrade Preflight — common product and monorepo Wiki · Common repository
- Home
- Key Concepts
- Package Map
- Class and Service Index
- Getting Started
- CLI Reference
- Artisan Command
- Reading the Report
- Safety and Trust Boundaries
- Troubleshooting and FAQ
- Architecture Overview
- Core Package Guide
- Core Analysis Pipeline
- Core Service Reference
- Determinism and Evidence
- Report Schema
- CLI Package Internals
- Laravel Package Internals
- Test Adapters
- Writing a Framework Adapter
- Laravel Adapter Internals
- Contributing
- Roadmap and Status
- Tools Reference
- Quality and Release Tooling
- Release Wiki Strategy