tobi/qmd · error · Error
Failed to write ${configPath}: ${error}
Error message
Failed to write ${configPath}: ${error} What it means
saveConfig could not write the serialized YAML config to disk; writeFileSync threw (EACCES, ENOSPC, EISDIR, readonly path, etc.) and the error is wrapped with the target path. It is raised by every operation that mutates collections (add/remove/rename, settings updates).
Source
Thrown at src/collections.ts:231
if (configSource.type === 'inline') {
configSource.config = config;
return;
}
const configPath = configSource.path || getConfigFilePath();
const configDir = dirname(configPath);
if (!existsSync(configDir)) {
mkdirSync(configDir, { recursive: true });
}
try {
const yaml = YAML.stringify(config, {
indent: 2,
lineWidth: 0, // Don't wrap lines
});
writeFileSync(configPath, yaml, "utf-8");
} catch (error) {
throw new Error(`Failed to write ${configPath}: ${error}`);
}
}
/**
* Get a specific collection by name
* Returns null if not found
*/
export function getCollection(name: string): NamedCollection | null {
const config = loadConfig();
const collection = config.collections[name];
if (!collection) {
return null;
}
return { name, ...collection };
}
View on GitHub (pinned to dbfd0b4736)
Solutions
- Check permissions/ownership of the config path named in the message and chown/chmod it
- Free disk space or remount the filesystem read-write
- Avoid running qmd with sudo so configs aren't written as root
- Pass an explicit writable configPath when running in containers/CI
Defensive patterns
Strategy: try-catch
Validate before calling
import { accessSync, constants } from 'node:fs';
import { dirname } from 'node:path';
function configWritable(configPath: string): boolean {
try {
accessSync(dirname(configPath), constants.W_OK);
return true;
} catch { return false; }
} Try / catch
try {
await store.addCollection?.(name, path);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Failed to write')) {
// show path, check permissions/disk, surface to user
} else throw e;
} Prevention
- Never run qmd with sudo
- Ensure the config directory is user-writable
- Keep disk space monitored on CI/long-running machines
When it happens
Trigger: Running qmd collection add/remove/rename when the config path is read-only, owned by another user, on a full disk, or when the path is a directory.
Common situations: Configs under a root-owned /etc or ~/.config after running qmd once with sudo; disk-full CI runners; immutable container filesystems; two qmd processes racing on the same config.
Related errors
- Refusing to initialize a local index in $HOME. The global in
- Collection name is required. Collections must be defined in
- Skill already exists: ${targetDir} (use --force to replace i
- Failed to parse ${configPath}: ${error}
- Invalid expandContextSize: ${configValue}. Must be a positiv
AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28).
Data as JSON: /api/errors/de0c21b0dec83072.
Report an issue: GitHub.