different-ai/openwork · error

constants.json is missing opencodeVersion

Error message

constants.json is missing opencodeVersion

What it means

pinnedOpencodeInstallCommand() reads the repo-root constants.json to find the pinned opencode version used when installing OpenCode. If the JSON parses but has no non-empty `opencodeVersion` field, this error is thrown because no install command can be constructed. It indicates a broken or outdated constants.json in the desktop workspace.

Source

Thrown at apps/desktop/electron/runtime.mjs:1773

      found: true,
      inPath: resolved.source === "path",
      resolvedPath: resolved.path,
      resolvedSource: resolved.source,
      version: versionResult.stdout?.trim() || versionResult.stderr?.trim() || null,
      supportsServe: helpResult.status === 0,
      notes,
      serveHelpStatus: typeof helpResult.status === "number" ? helpResult.status : null,
      serveHelpStdout: helpResult.stdout?.trim() || null,
      serveHelpStderr: helpResult.stderr?.trim() || null,
    };
  }

  async function pinnedOpencodeInstallCommand() {
    const constantsPath = path.resolve(desktopRoot, "../../constants.json");
    const payload = JSON.parse(await readFile(constantsPath, "utf8"));
    const version = String(payload?.opencodeVersion ?? "").trim().replace(/^v/, "");
    if (!version) {
      throw new Error("constants.json is missing opencodeVersion");
    }
    return `curl -fsSL https://opencode.ai/install | bash -s -- --version ${version} --no-modify-path`;
  }

  function processMatchesSidecar(command) {
    return commandMatchesPackagedSidecar(command, sidecarDirs);
  }

  function killProcessId(pid, signal = "SIGTERM") {
    if (!Number.isFinite(pid) || pid <= 0 || pid === process.pid) return;
    try {
      process.kill(pid, signal);
    } catch {
      // Process already exited or is not ours.
    }
  }

  async function cleanupPackagedSidecars() {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Add or restore `"opencodeVersion": "x.y.z"` in constants.json at the repo root.
  2. Verify the key name is exactly `opencodeVersion` (camelCase) and its value is a non-empty version string (leading `v` is stripped automatically).
  3. Re-run the repo's constants/update script that normally generates constants.json.
  4. Commit a valid constants.json or regenerate it if it was gitignored and lost on a clean clone.

Example fix

// before (constants.json)
{ "opencodeVersion": "" }
// after
{ "opencodeVersion": "1.0.4" }
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from "node:fs";
const constantsPath = path.resolve(desktopRoot, "../../constants.json");
const payload = JSON.parse(readFileSync(constantsPath, "utf8"));
const version = typeof payload?.opencodeVersion === "string" && payload.opencodeVersion.trim() ? payload.opencodeVersion.trim().replace(/^v/, "") : null;
if (!version) throw new Error(`opencodeVersion missing or empty in ${constantsPath}`);

Type guard

function hasOpencodeVersion(p) {
  return typeof p === "object" && p !== null && typeof p.opencodeVersion === "string" && p.opencodeVersion.trim().length > 0;
}

Try / catch

try {
  const cmd = await pinnedOpencodeInstallCommand();
} catch (err) {
  if (err.message.includes("missing opencodeVersion")) {
    logError("constants.json is malformed; regenerating from template");
  } else { throw err; }
}

Prevention

When it happens

Trigger: constants.json at desktopRoot/../../constants.json exists and parses as JSON, but `payload.opencodeVersion` is undefined, null, an empty string, or only whitespace (e.g. "" or "v").

Common situations: A fresh checkout or generated constants.json that omits opencodeVersion; a manual edit or merge that removed the key; a version-pinning script that wrote an empty value; a typo like `openCodeVersion` in the JSON.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/c9d5ba6cb4044850. Report an issue: GitHub.