multica-ai/multica · error · Error
mint PAT: response missing token
Error message
mint PAT: response missing token
What it means
Thrown by prepareHermesHome when os.MkdirAll cannot create the per-task overlay directory <envRoot>/hermes-home with mode 0700. The overlay holds the mirrored shared home plus a derived config that can contain inline api_key secrets, which is why the daemon insists on creating it with tight permissions.
Source
Thrown at apps/desktop/src/main/daemon-manager.ts:627
"Content-Type": "application/json",
Authorization: `Bearer ${jwt}`,
},
// Omit expires_in_days → server treats as null → non-expiring PAT.
body: JSON.stringify({ name: "Multica Desktop" }),
});
if (!res.ok) {
const body = await res.text().catch(() => "");
// Attach the status so callers can tell a genuine auth rejection (401 — the
// session token is dead) apart from a transient failure (5xx, etc.) without
// string-matching the message.
throw Object.assign(
new Error(`mint PAT failed: ${res.status} ${res.statusText} ${body}`),
{ status: res.status },
);
}
const data = (await res.json()) as { token?: unknown };
if (typeof data.token !== "string" || !data.token.startsWith("mul_")) {
throw new Error("mint PAT: response missing token");
}
return data.token;
}
/**
* Ensure the active profile's config.json has a usable token for the daemon.
*
* - Input from the renderer is the user's JWT (from localStorage) plus the
* current user's id, so we can detect session changes.
* - If the profile already has a cached PAT (`mul_...`) AND the sidecar user
* id matches the caller, reuse it — minting fresh on every launch would
* accumulate garbage in the user's tokens page.
* - On user mismatch (or first run) call POST /api/tokens with the JWT to
* mint a fresh PAT, overwriting any stale cached PAT. This is the critical
* path: without it, a previous user's PAT would be used by a new session.
* - If the caller happens to pass a PAT directly, write it through.
* - When we mint fresh and a daemon is already running, restart it so the
* new credentials take effect (the Go daemon reads config at startup).View on GitHub (pinned to 2c0912b6ec)
Solutions
- Inspect the wrapped *PathError for the failing path; ensure every parent directory is writable and owned by the daemon user.
- Remove any stale non-directory file occupying the hermes-home path.
- Free disk space or remount the env-root volume read-write.
- Restart the daemon as the user that owns the env-root (or chown the env-root to the daemon user).
Example fix
# before $ ls -l /var/lib/app/envs/task-9/hermes-home -rw-r--r-- 1 root root 0 ... hermes-home # stale file blocks MkdirAll # after $ rm /var/lib/app/envs/task-9/hermes-home && chown -R daemonuser /var/lib/app/envs
Defensive patterns
Strategy: try-catch
Validate before calling
if err := checkWritable(filepath.Dir(envRoot)); err != nil {
return fmt.Errorf("env-root parent not writable: %w", err)
} Try / catch
if err := prepareHermesHome(...); err != nil {
if strings.Contains(err.Error(), "create hermes-home dir") {
var pe *os.PathError
if errors.As(err, &pe) {
// pe.Path names the failing component; fix perms/space, retry once
}
}
} Prevention
- Ensure the daemon user owns env-root directories.
- Disk-space monitoring on the env-root volume.
- GC stale per-task env-roots so MkdirAll never hits stray files.
When it happens
Trigger: prepareHermesHome runs and MkdirAll(hermesHome, 0o700) fails: a parent in envRoot is not writable by the daemon user, a non-directory file already exists somewhere along the path, the filesystem is full or read-only, or a symlink loop exists.
Common situations: env-root created by root while the daemon runs unprivileged; a leftover file named 'hermes-home' from an aborted run; disk exhaustion on the task volume; read-only container layer where env-root was not mounted as writable.
Related errors
- daemon profile is not resolved yet; token sync skipped
- runtime local skill discovery timed out
- runtime local skill import failed
- mint PAT: target API URL not set
- API error: ${res.status} ${res.statusText}
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/4e523a4826d2d9f7.
Report an issue: GitHub.