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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions