actualbudget/actual · error · Error
Failed to copy SQL file from ${frompath} to ${topath}: ${sec
Error message
Failed to copy SQL file from ${frompath} to ${topath}: ${secondError.message} What it means
`copyFile` first tries a regular write-based copy; when either path is a `.sqlite` database it falls back to `_copySqlFile` (SQL dump/re-import). If that fallback also fails, the underlying error is rethrown with full source/destination context.
Source
Thrown at packages/loot-core/src/platform/server/fs/index.ts:393
export const size = async function (filepath) {
const attrs = FS.stat(resolveLink(filepath));
return attrs.size;
};
export const copyFile = async function (
frompath: string,
topath: string,
): Promise<boolean> {
let result = false;
try {
const contents = await _readFile(frompath);
result = await _writeFile(topath, contents);
} catch (error) {
if (frompath.endsWith('.sqlite') || topath.endsWith('.sqlite')) {
try {
result = await _copySqlFile(frompath, topath);
} catch (secondError) {
throw new Error(
`Failed to copy SQL file from ${frompath} to ${topath}: ${secondError.message}`,
);
}
} else {
throw error;
}
}
return result;
};
export async function readFile(
filepath: string,
encoding?: 'utf8',
): Promise<string>;
export async function readFile(
filepath: string,
encoding: 'binary',
): Promise<Uint8Array>;View on GitHub (pinned to d4334cb6e6)
Solutions
- Read the inner `secondError.message` in the thrown text — it names the actual failing step (read vs write)
- Verify the source `.sqlite` opens correctly (e.g. try loading the budget) and repair or restore from backup if corrupt
- Check free storage/quota and write permissions for the destination path
- Retry the copy after closing other connections to the database
Defensive patterns
Strategy: retry
Validate before calling
import { exists } from './platform/server/fs';
if (!(await exists(frompath))) throw new Error(`Source missing: ${frompath}`);
// ensure destination dir is writable before copying Try / catch
try {
await fs.copyFile(from, to);
} catch (e) {
if (String(e).startsWith('Failed to copy SQL file')) {
// parse inner error; verify source DB integrity, free space, then retry once
} else throw e;
} Prevention
- Avoid copying .sqlite files while the budget is open/locked
- Check storage quota before large DB copies
- Back up budgets through the app's export feature instead of raw file copies
When it happens
Trigger: `copyFile(frompath, topath)` where a path ends in `.sqlite` and `_copySqlFile` throws — corrupt source DB, failed export, or a failed write of the destination SQL file.
Common situations: Duplicating or backing up a budget while the database is locked/corrupt; destination path unwritable (quota exceeded, permission error); interrupted earlier write leaving a broken sqlite file.
Related errors
- ACTUAL_DATA_DIR env variable is required
- File does not exist: ${filepath}
- getModifiedTime not supported on the web (only used for back
- invalid-schema
- Failed to delete user access: ${error.message}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/634cae007cce04db.
Report an issue: GitHub.