What happened?
Command pi update outputs Error: Could not determine latest pi version when environment variable PI_SKIP_VERSION_CHECK is set.
Steps to reproduce
Steps to Reproduce
- Export the skip-check variable:
export PI_SKIP_VERSION_CHECK=1
- Run:
- Observe the error:
Error: Could not determine latest pi version.
Expected behavior
Pi should update instead of outputing an error.
Root Cause
The user intent behind PI_SKIP_VERSION_CHECK is to suppress the passive startup version nag. However, the same variable is honored inside the low-level fetch helper, so it also short-circuits the explicit, user-initiated pi update command.
dist/utils/version-check.js
getLatestPiRelease() returns undefined immediately when the variable is set, before any network request is made:
export async function getLatestPiRelease(currentVersion, options = {}) {
if (process.env.PI_SKIP_VERSION_CHECK || process.env.PI_OFFLINE)
return undefined;
const response = await fetch(LATEST_VERSION_URL, { /* ... */ });
// ...
}
dist/package-manager-cli.js
getSelfUpdatePlan() then treats that undefined as a hard failure:
async function getSelfUpdatePlan(force) {
let latestRelease;
try {
latestRelease = await getLatestPiRelease(VERSION);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Could not determine latest ${APP_NAME} version: ${message}`);
}
if (!latestRelease) {
throw new Error(`Could not determine latest ${APP_NAME} version.`);
}
// ...
}
Because the early return undefined produces no thrown error, execution reaches the if (!latestRelease) branch, which throws the message with no trailing detail — exactly the text the user sees. (A network/HTTP failure would instead produce the variant with a trailing : <message>.)
PI_OFFLINE has the same effect and is arguably correct for an offline mode, but PI_SKIP_VERSION_CHECK conflating "don't nag me at startup" with "don't ever check, even when I explicitly ask" is the surprising part.
Impact
Any user who sets PI_SKIP_VERSION_CHECK (a common way to quiet the startup notification) cannot use pi update at all. The error message gives no hint that an environment variable is responsible, making it hard to diagnose.
Proposed Fix
Separate the passive version check (startup nag) from the active update path. The explicit pi update command should ignore PI_SKIP_VERSION_CHECK.
Option A (preferred): add an opt-in bypass and use it from the updater
In utils/version-check.js, allow callers to force the check regardless of the skip flag:
export async function getLatestPiRelease(currentVersion, options = {}) {
const skip = process.env.PI_SKIP_VERSION_CHECK || process.env.PI_OFFLINE;
if (skip && !options.force)
return undefined;
const response = await fetch(LATEST_VERSION_URL, {
headers: {
"User-Agent": getPiUserAgent(currentVersion),
accept: "application/json",
},
signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_VERSION_CHECK_TIMEOUT_MS),
});
// ... unchanged ...
}
Then, in package-manager-cli.js, the explicit update path passes force: true:
async function getSelfUpdatePlan(force) {
let latestRelease;
try {
latestRelease = await getLatestPiRelease(VERSION, { force: true });
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Could not determine latest ${APP_NAME} version: ${message}`);
}
if (!latestRelease) {
throw new Error(`Could not determine latest ${APP_NAME} version.`);
}
// ...
}
The passive startup check (checkForNewPiVersion) continues to honor PI_SKIP_VERSION_CHECK by not passing force, so the startup nag stays suppressed as intended.
Note: PI_OFFLINE could reasonably continue to short-circuit even the forced path, since there is genuinely no network. If so, split the condition:
if (process.env.PI_OFFLINE)
return undefined;
if (process.env.PI_SKIP_VERSION_CHECK && !options.force)
return undefined;
Option B (minimal): improve the diagnostic
If the current behavior is intentional, at least make the error actionable when the variable is the cause:
if (!latestRelease) {
if (process.env.PI_SKIP_VERSION_CHECK || process.env.PI_OFFLINE) {
throw new Error(
`Could not determine latest ${APP_NAME} version because ` +
`PI_SKIP_VERSION_CHECK or PI_OFFLINE is set. Unset it and retry.`);
}
throw new Error(`Could not determine latest ${APP_NAME} version.`);
}
Option A is recommended because it makes pi update do what the user explicitly asked, regardless of the passive-notification preference.
Version
0.80.3
What happened?
Command
pi updateoutputsError: Could not determine latest pi versionwhen environment variable PI_SKIP_VERSION_CHECK is set.Steps to reproduce
Steps to Reproduce
export PI_SKIP_VERSION_CHECK=1Expected behavior
Pi should update instead of outputing an error.
Root Cause
The user intent behind
PI_SKIP_VERSION_CHECKis to suppress the passive startup version nag. However, the same variable is honored inside the low-level fetch helper, so it also short-circuits the explicit, user-initiatedpi updatecommand.dist/utils/version-check.jsgetLatestPiRelease()returnsundefinedimmediately when the variable is set, before any network request is made:dist/package-manager-cli.jsgetSelfUpdatePlan()then treats thatundefinedas a hard failure:Because the early
return undefinedproduces no thrown error, execution reaches theif (!latestRelease)branch, which throws the message with no trailing detail — exactly the text the user sees. (A network/HTTP failure would instead produce the variant with a trailing: <message>.)PI_OFFLINEhas the same effect and is arguably correct for an offline mode, butPI_SKIP_VERSION_CHECKconflating "don't nag me at startup" with "don't ever check, even when I explicitly ask" is the surprising part.Impact
Any user who sets
PI_SKIP_VERSION_CHECK(a common way to quiet the startup notification) cannot usepi updateat all. The error message gives no hint that an environment variable is responsible, making it hard to diagnose.Proposed Fix
Separate the passive version check (startup nag) from the active update path. The explicit
pi updatecommand should ignorePI_SKIP_VERSION_CHECK.Option A (preferred): add an opt-in bypass and use it from the updater
In
utils/version-check.js, allow callers to force the check regardless of the skip flag:Then, in
package-manager-cli.js, the explicit update path passesforce: true:The passive startup check (
checkForNewPiVersion) continues to honorPI_SKIP_VERSION_CHECKby not passingforce, so the startup nag stays suppressed as intended.Note:
PI_OFFLINEcould reasonably continue to short-circuit even the forced path, since there is genuinely no network. If so, split the condition:Option B (minimal): improve the diagnostic
If the current behavior is intentional, at least make the error actionable when the variable is the cause:
Option A is recommended because it makes
pi updatedo what the user explicitly asked, regardless of the passive-notification preference.Version
0.80.3