multica-ai/multica · error · Error

Invalid desktop runtime config: ${field} must be a non-empty

Error message

Invalid desktop runtime config: ${field} must be a non-empty string

What it means

Wrap thrown by execenv.Prepare when writeSidecarManifest cannot record the manifest of sidecar files written into the environment root. Its severity is conditional: when params.LocalWorkDir is set (in-place run into the user's own directory) the manifest is the ONLY record of what was written there, so losing it strands the sidecar tree permanently (issue MUL-6132) — Prepare fails so the registered rollback removes the tree now. Otherwise the manifest is a GC convenience and the error is only logged as a warning.

Source

Thrown at apps/desktop/src/shared/runtime-config.ts:129

}

// Dev variant: when the api host is the local backend (`localhost:8080` /
// `127.0.0.1:8080`), the renderer is served from a different port (3000),
// so deriving by host alone is wrong. Fall back to the local dev web URL
// in that case; for any non-local host (e.g. a remote test environment),
// trust the production-style derivation so `apiUrl=https://api.test.x`
// yields `appUrl=https://test.x` without a separate VITE_APP_URL.
export function deriveDevAppUrl(apiUrl: string): string {
  const url = new URL(apiUrl);
  if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
    return LOCAL_DEV_RUNTIME_CONFIG.appUrl;
  }
  return deriveAppUrl(apiUrl);
}

function requiredString(value: unknown, field: string): string {
  if (typeof value !== "string" || value.trim().length === 0) {
    throw new Error(`Invalid desktop runtime config: ${field} must be a non-empty string`);
  }
  return value;
}

function optionalString(value: unknown, field: string): string | undefined {
  if (value === undefined) return undefined;
  if (typeof value !== "string" || value.trim().length === 0) {
    throw new Error(`Invalid desktop runtime config: ${field} must be a non-empty string when set`);
  }
  return value;
}

function normalizeHttpUrl(value: string, field: string): string {
  let url: URL;
  try {
    url = new URL(value.trim());
  } catch {
    throw new Error(`Invalid desktop runtime config: ${field} must be a valid URL`);

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Verify the env-root (and, for in-place runs, the local work dir) is writable and has space for the manifest file.
  2. If the failure is transient (NFS hiccup, disk momentarily full), free space and re-run the task — the rollback will have cleaned the stranded tree, so the retry starts clean.
  3. Check for a stale directory or symlink occupying the manifest path and remove it.
  4. If running in-place frequently, monitor disk health of the user directory; a manifest write failing there is the signal the sidecar rollback path also depends on.
Defensive patterns

Strategy: try-catch

Validate before calling

if params.LocalWorkDir != "" {
    // in-place runs: manifest write is load-bearing, pre-check writability
    if err := checkWritable(params.LocalWorkDir); err != nil {
        return fmt.Errorf("local work dir not writable: %w", err)
    }
}

Try / catch

if err := execenv.Prepare(ctx, params); err != nil {
    if strings.Contains(err.Error(), "write sidecar manifest") && params.LocalWorkDir != "" {
        // rollback already ran; clean any residue, fix disk/perms, retry once
    }
}

Prevention

When it happens

Trigger: writeSidecarManifest(envRoot, manifest) returns an error. It becomes this returned error only when params.LocalWorkDir != "" (in-place run); with an empty LocalWorkDir the same failure is downgraded to logger.Warn("execenv: write sidecar manifest failed (non-fatal)").

Common situations: In-place task targeting a user directory on a read-only or full filesystem; transient disk/permission hiccup exactly between writing the sidecar tree and its manifest; a manifest path colliding with a directory.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/f4b5576a68bd4fa3. Report an issue: GitHub.