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

  1. Treat this as expected: filter linked extensions out of update batches before calling checkForExtensionUpdate.
  2. Update the linked extension by pulling/rebuilding its source directory directly.
  3. 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

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


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/9a3dadd91cc1437d. Report an issue: GitHub.