Skip to content

auto-update: preparePackageUpdate fails when cache dir lacks root package.json #73

@HaleTom

Description

@HaleTom

What happened?

resolveInstallContext() in src/hooks/auto-update-checker/cache.ts assumes the cache install directory always has a root-level package.json. When it's missing — e.g. OpenCode's plugin cache extracts only node_modules/ without a root package.jsonpreparePackageUpdate() returns null and the user sees: "Auto-update could not prepare the active install." even though ~/.cache/opencode/packages/ is writable.

Root cause

In resolveInstallContext() (line 166451 in the built dist/index.js):

function resolveInstallContext(runtimePackageJsonPath) {
  if (runtimePackageJsonPath) {
    const packageDir = dirname(runtimePackageJsonPath);           // → .../opencode-magic-context
    const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME); // → .../.cache/.../node_modules
    if (nodeModulesDir && basename(nodeModulesDir) === "node_modules") {
      const installDir = dirname(nodeModulesDir);                  // → .../opencode-magic-context@latest/
      const packageJsonPath = join(installDir, "package.json");    // → .../package.json ← DOES NOT EXIST
      if (existsSync(packageJsonPath))                             // FAILS HERE
        return { installDir, packageJsonPath };
    }
    return null;  // ← returns null; legacy fallback is NEVER reached
  }
  // This legacy fallback (packages/package.json) is unreachable because
  // runtimePackageJsonPath is always truthy when found from the module location
  const legacyPackageJsonPath = join(dirname(CACHE_DIR), "package.json");
  if (existsSync(legacyPackageJsonPath)) { ... }
  return null;
}

Two issues:

  1. Missing package.json aborts the entire path. The primary install context check returns null immediately when the root package.json is missing, even though node_modules/ exists and npm install could still proceed.

  2. Legacy fallback is unreachable. Because runtimePackageJsonPath is always truthy (found from the runtime module's own package.json), the legacy fallback path (packages/package.json) at the bottom of the function is dead code under this condition.

Suggested improvements

  • If the primary path finds node_modules/ but no root package.json, create one instead of returning null:
    if (!existsSync(packageJsonPath)) {
      writeFileSync(packageJsonPath, JSON.stringify({ private: true, dependencies: {} }, null, 2));
    }
    return { installDir, packageJsonPath };
  • Or fall through to the legacy path instead of the early return null.

Environment

  • Plugin version: 0.18.0 (trying to update to 0.19.0)
  • Cache path: ~/.cache/opencode/packages/@cortexkit/opencode-magic-context@latest/ (contains only node_modules/, no package.json)
  • OpenCode TUI (CLI), linux x64
  • ~/.cache/opencode mount is rw btrfs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions