Budibase/budibase · error · HTTPError
Project import failed while saving
Error message
Project import failed while saving '${failedId}'. What it means
This error is thrown at the end of a project import when at least one document read from the exported package failed to save into the target database. The import loop records the _id of the first doc whose save returned an error, a missing id, or a missing rev, then aborts the whole import with an HTTP 400 naming that doc. It means the package parsed fine but persistence of one or more docs failed.
Solutions
- Inspect the failedId named in the message in the extracted package and fix or remove the offending document
- Re-export the package from a source workspace on the same (or compatible) Budibase version instead of hand-editing files
- Check CouchDB health, disk space and write quota on the target environment and retry
- Retry the import; if a doc conflicts, delete the conflicting doc in the target or import into a fresh workspace
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-import: ensure the package is a valid tarball and target DB is healthy
const stats = await fsp.stat(packagePath)
if (stats.size === 0) throw new Error('package is empty')
const health = await fetch(`${couchDbUrl}/_up`)
if (!health.ok) throw new Error('target database not healthy') Type guard
function hasSaveResultIdRev(r: { error?: unknown; id?: unknown; rev?: unknown }): r is { error?: undefined; id: string; rev: string } {
return !r.error && typeof r.id === 'string' && r.id.length > 0 && typeof r.rev === 'string' && r.rev.length > 0
} Try / catch
try {
await importProjectPackage(file)
} catch (err) {
if (err instanceof HTTPError && err.status === 400 && err.message.includes('import failed while saving')) {
const failedId = err.message.match(/'(.+)'/)?.[1]
// inspect/repair the failing doc or retry against a fresh workspace
} else {
throw err
}
} Prevention
- Never hand-edit documents inside an exported package; always re-export from the source workspace
- Keep source and target Budibase versions compatible before importing
- Monitor CouchDB disk space and quotas in target environments
- Test imports against a staging workspace before production
When it happens
Trigger: Calling the project import API (POST import of a project package tarball) where one doc's save result has error set, or no _id/_rev, in the loop at imports.ts:905; the thrown message names failedId (the first failing doc's _id).
Common situations: Corrupt or hand-edited package contents producing docs the DB rejects; CouchDB write failures (conflicts, disk full, quota); importing an export from an incompatible Budibase version whose doc shapes no longer validate; interrupted/partial packages.
Related errors
- Files are encrypted but no password has been supplied.
- _id and _rev are required
- Project package contains a doc without an id.
- Project package contains an invalid doc in
- Project package contains too many docs.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/ee251e61930d6d3c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/server/src/sdk/workspace/projects/backups/imports.ts:905
}>
let failedId: string | undefined
response.forEach((result, index) => {
if (result.id && result.rev) {
insertedDocs.push({
_id: result.id,
_rev: result.rev,
})
}
if (!failedId && (result.error || !result.id || !result.rev)) {
failedId = docs[index]._id
}
})
if (failedId) {
throw new HTTPError(
`Project import failed while saving '${failedId}'.`,
400
)
}
}
async function extractProjectPackage(
file: { path: string },
encryptPassword?: string
): Promise<ExtractedProjectPackage> {
const fileStats = await fsp.stat(file.path)
if (fileStats.size > MAX_ARCHIVE_SIZE_BYTES) {
throw new HTTPError("Project package is too large.", 400)
}
if (encryptPassword && encryptPassword.length > MAX_ENCRYPT_PASSWORD_LENGTH) {
throw new HTTPError("Project package password is too long.", 400)
}
View on GitHub (pinned to a81a902e9a)