multica-ai/multica · error

runtime local skill discovery failed

Error message

runtime local skill discovery failed

What it means

Wrap thrown by prepareHermesHome when writeDerivedHermesConfig fails. The derived config is re-derived from the shared home's config plus the task's env overrides and written into the overlay; it can hold inline api_key secrets. Fail-closed by design: a Hermes that would boot without the derived config could miss its providers/keys, so prepare aborts instead.

Source

Thrown at packages/core/runtimes/local-skills.ts:45

const IMPORT_POLL_TIMEOUT_MS = 4 * 60_000; // 4 minutes

export async function resolveRuntimeLocalSkills(
  runtimeId: string,
): Promise<RuntimeLocalSkillsResult> {
  const initial = await api.initiateListLocalSkills(runtimeId);
  const start = Date.now();
  let current = initial;

  while (current.status === "pending" || current.status === "running") {
    if (Date.now() - start > POLL_TIMEOUT_MS) {
      throw new Error("runtime local skill discovery timed out");
    }
    await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
    current = await api.getListLocalSkillsResult(runtimeId, initial.id);
  }

  if (current.status === "failed" || current.status === "timeout") {
    throw new Error(current.error || "runtime local skill discovery failed");
  }

  return {
    skills: current.skills ?? [],
    supported: current.supported,
	mcpServers: current.mcp_servers ?? [],
	mcpSupported: current.mcp_supported === true,
  };
}

export async function resolveRuntimeLocalSkillImport(
  runtimeId: string,
  payload: CreateRuntimeLocalSkillImportRequest,
): Promise<RuntimeLocalSkillImportResult> {
  const initial = await api.initiateImportLocalSkill(runtimeId, payload);
  const start = Date.now();
  let current = initial;

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Validate the shared home's config file parses (e.g. `hermes` CLI or a local parse) and repair syntax errors.
  2. Sanitize env override values passed via params.HermesEnv; drop keys that are not valid config inputs.
  3. Fix write permissions/ownership of the overlay's config path or delete the stale overlay.
  4. Free disk space and retry.

Example fix

# before: invalid line in shared config
$ cat ~/.hermes/config.toml
api_key =  broken  ← syntax error

# after
api_key = "sk-..."   # quoted, valid
Defensive patterns

Strategy: validation

Validate before calling

if _, err := toml.ParseFile(filepath.Join(sharedHome, "config.toml")); err != nil { // or hermes CLI check
    return fmt.Errorf("shared hermes config invalid: %w", err)
}

Try / catch

if err := prepareHermesHome(...); err != nil {
    if strings.Contains(err.Error(), "derive hermes config") {
        // surface the wrapped parse/write error; repair the shared config or env overrides; no silent minimal-config fallback
    }
}

Prevention

When it happens

Trigger: writeDerivedHermesConfig(sharedHome, hermesHome, env, logger) errors — the shared config is unreadable or unparseable, a required value cannot be rendered, or the derived file cannot be written into hermes-home (permissions/full disk).

Common situations: User hand-edited the shared hermes config into invalid syntax; env override map contains values that cannot be represented in the config format; leftover derived config in a recycled overlay owned by another user; env var interpolation producing invalid content.

Related errors


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