{"record":{"id":"4d7034f028c80b6b","repo":"gastownhall/beads","slug":"backup-destination-is-not-a-directory-s-4d7034","errorCode":null,"errorMessage":"backup destination is not a directory: %s","messagePattern":"backup destination is not a directory: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/embeddeddolt/version_control.go","lineNumber":737,"sourceCode":"\t})\n}\n\nfunc (s *EmbeddedDoltStore) BackupRemove(ctx context.Context, name string) error {\n\treturn s.withMutatingDBConn(ctx, func(db versioncontrolops.DBConn) error {\n\t\treturn versioncontrolops.BackupRemove(ctx, db, name)\n\t})\n}\n\n// BackupDatabase registers dir as a file:// Dolt backup remote and syncs\n// the database to it. The dir must exist locally. This preserves full Dolt\n// commit history.\nfunc (s *EmbeddedDoltStore) BackupDatabase(ctx context.Context, dir string) error {\n\tinfo, err := os.Stat(dir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"backup destination does not exist: %w\", err)\n\t}\n\tif !info.IsDir() {\n\t\treturn fmt.Errorf(\"backup destination is not a directory: %s\", dir)\n\t}\n\n\tbackupURL, err := versioncontrolops.DirToFileURL(dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbackupName := \"backup_export\"\n\n\treturn s.withMutatingDBConn(ctx, func(db versioncontrolops.DBConn) error {\n\t\t// Register as a backup remote (idempotent — remove first if exists).\n\t\t_ = versioncontrolops.BackupRemove(ctx, db, backupName)\n\t\tif err := versioncontrolops.BackupAdd(ctx, db, backupName, backupURL); err != nil {\n\t\t\t// Another backup (e.g. \"default\" registered by `bd backup init`) may\n\t\t\t// already point to this URL. In that case, sync using the existing\n\t\t\t// remote name rather than failing.\n\t\t\tif conflict := versioncontrolops.ExtractAddressConflictName(err); conflict != \"\" {\n\t\t\t\tif syncErr := versioncontrolops.BackupSync(ctx, db, conflict); syncErr != nil {\n\t\t\t\t\treturn fmt.Errorf(\"sync to backup: %w\", syncErr)","sourceCodeStart":719,"sourceCodeEnd":755,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/version_control.go#L719-L755","documentation":"Returned by BackupDatabase when the destination path exists but is a regular file (or other non-directory), not a directory. Dolt file:// backup remotes must point at a directory, so the store rejects the argument with this plain (non-wrapped) message.","triggerScenarios":"Calling BackupDatabase(ctx, dir) where os.Stat(dir) succeeds but info.IsDir() is false — e.g. passing a tarball path, a config file, or the database file itself instead of a directory.","commonSituations":"Pointing backup at an archive file expecting it to 'restore into' it; passing the .bdb/db file instead of its parent directory; a symlink resolving to a file.","solutions":["Pass a directory path, not a file: mkdir the intended backup dir and re-run","If a file exists at the path, remove/rename it and create a directory","Verify with `ls -la <path>` that the target is a directory","Use DirToFileURL-compatible absolute directory paths"],"exampleFix":"// before\nstore.BackupDatabase(ctx, \"/backups/beads.tar.gz\") // a file\n// after\nos.MkdirAll(\"/backups/beads\", 0o755)\nstore.BackupDatabase(ctx, \"/backups/beads\")","handlingStrategy":"validation","validationCode":"info, err := os.Stat(dir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"%%s must be an existing directory\", dir)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Point backups at directories, never files or archives","Verify targets with ls -la in setup scripts","Avoid symlink chains that can resolve to files"],"tags":["go","dolt","backup","filesystem"],"backgroundTag":"path-not-a-directory","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}