google-gemini/gemini-cli · info · Error
Extension is linked so does not need to be updated
Error message
Extension is linked so does not need to be updated
What it means
Thrown by checkForExtensionUpdate when installMetadata.type === 'link'. Linked extensions are local symlinks used during development, so there is no remote source to update from; the code sets the state to UP_TO_DATE and throws to short-circuit the update flow.
Source
Thrown at packages/cli/src/config/extensions/update.ts:80
if (status === IntegrityDataStatus.INVALID) {
throw new Error('Extension integrity cannot be verified');
}
} catch (e) {
dispatchExtensionStateUpdate({
type: 'SET_STATE',
payload: { name: extension.name, state: ExtensionUpdateState.ERROR },
});
throw new Error(
`Extension ${extension.name} cannot be updated. ${getErrorMessage(e)}. To fix this, reinstall the extension.`,
);
}
if (installMetadata?.type === 'link') {
dispatchExtensionStateUpdate({
type: 'SET_STATE',
payload: { name: extension.name, state: ExtensionUpdateState.UP_TO_DATE },
});
throw new Error(`Extension is linked so does not need to be updated`);
}
if (extension.migratedTo) {
const migratedState = await checkForExtensionUpdate(
{
...extension,
installMetadata: { ...installMetadata, source: extension.migratedTo },
migratedTo: undefined,
},
extensionManager,
);
if (
migratedState === ExtensionUpdateState.UPDATE_AVAILABLE ||
migratedState === ExtensionUpdateState.UP_TO_DATE
) {
installMetadata.source = extension.migratedTo;
}
}View on GitHub (pinned to 5024443c72)
Solutions
- Treat this as expected: filter linked extensions out of update batches before calling checkForExtensionUpdate.
- Update the linked extension by pulling/rebuilding its source directory directly.
- Unlink and install normally if you want remote updates.
Example fix
// before
for (const ext of extensions) await checkForExtensionUpdate(ext, mgr);
// after
for (const ext of extensions) {
const meta = loadInstallMetadata(ext.path);
if (meta?.type === 'link') continue;
await checkForExtensionUpdate(ext, mgr);
} Defensive patterns
Strategy: type-guard
Validate before calling
const meta = loadInstallMetadata(ext.path);
if (meta?.type === 'link') { /* skip update check */ } Type guard
function isLinkedExtension(meta?: ExtensionInstallMetadata): boolean { return meta?.type === 'link'; } Try / catch
try { await checkForExtensionUpdate(ext, mgr); } catch (e) { if (/linked so does not need/.test(String(e))) { /* expected, ignore */ } else throw e; } Prevention
- Filter type:'link' extensions out of update batches.
- Update linked extensions from their source directory instead of via the updater.
When it happens
Trigger: Running an update check (batch or single) against an extension that was installed via 'gemini extensions link' / type:'link' rather than cloned or downloaded.
Common situations: Developing an extension locally with a symlink and then triggering the updater; a CI image that links extensions for testing and then runs update checks.
Related errors
- Extension ${extension.name} cannot be updated, type is unkno
- Extension ${extension.name} cannot be updated. ${getErrorMes
- Updated extension not found after installation, got error:\n
- Invalid scope: ${argv.scope}. Please use one of ${Object.val
- Invalid scope: ${argv.scope}. Please use one of ${Object.val
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/9a3dadd91cc1437d.
Report an issue: GitHub.