{"record":{"id":"478e10d45ed7f0ca","repo":"hashicorp/nomad","slug":"failed-to-create-migration-marker-w","errorCode":null,"errorMessage":"failed to create migration marker: %w","messagePattern":"failed to create migration marker: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/raftutil/migrate.go","lineNumber":72,"sourceCode":"\t\t\tclose(progress)\n\t\t}\n\t}()\n\n\tboltPath := filepath.Join(raftDir, \"raft.db\")\n\twalDir := filepath.Join(raftDir, \"wal\")\n\tmarkerPath := filepath.Join(raftDir, migrationMarkerFile)\n\n\tsendProgress(progress, \"starting migration pre-flight checks\")\n\n\tif err := preflightChecks(boltPath, walDir, raftDir); err != nil {\n\t\treturn err\n\t}\n\n\tsendProgress(progress, \"pre-flight checks passed\")\n\n\t// Create marker file to detect if server accidentally starts during migration.\n\tif err := os.WriteFile(markerPath, []byte(time.Now().Format(time.RFC3339)), 0o600); err != nil {\n\t\treturn fmt.Errorf(\"failed to create migration marker: %w\", err)\n\t}\n\tdefer os.Remove(markerPath) // Clean up marker on completion or failure.\n\n\t// Open the source BoltDB store.\n\tsrc, err := raftboltdb.New(raftboltdb.Options{\n\t\tPath: boltPath,\n\t\tBoltOptions: &bbolt.Options{\n\t\t\tTimeout: 5 * time.Second,\n\t\t},\n\t\tMsgpackUseNewTimeFormat: true,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open BoltDB store: %w\", err)\n\t}\n\n\t// Create the destination WAL store.\n\tif err := os.MkdirAll(walDir, 0o700); err != nil {\n\t\tsrc.Close()","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/raftutil/migrate.go#L54-L90","documentation":"MigrateToWAL fails when it cannot write the migration marker file used to detect if a server accidentally starts mid-migration. The marker is written with mode 0600 next to the data dir before opening the source store.","triggerScenarios":"Calling MigrateToWAL when the data directory is read-only, the process lacks write permission, the disk is full, or markerPath points at an unwritable location.","commonSituations":"Running the migration tool as a non-root user against a root-owned Nomad data dir; performing migration on a read-only mounted volume; SELinux/AppArmor blocking file creation.","solutions":["Run the migration as a user with write access to the data directory (or fix ownership: chown)","Ensure the filesystem is mounted read-write and has free space","Check for MAC policies (SELinux/AppArmor) denying writes if permissions look correct"],"exampleFix":"// before\nerr := raftutil.MigrateToWAL(dataDir)\n// after\nif err := checkDirWritable(dataDir); err != nil {\n    return fmt.Errorf(\"cannot write to %s: run migration as the nomad user\", dataDir)\n}\nerr := raftutil.MigrateToWAL(dataDir)","handlingStrategy":"validation","validationCode":"probe := filepath.Join(dataDir, \".write-test\")\nif err := os.WriteFile(probe, nil, 0o600); err != nil {\n    return fmt.Errorf(\"data dir not writable: run as the nomad user or fix mounts: %w\", err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"if err := raftutil.MigrateToWAL(dataDir); err != nil {\n    if strings.Contains(err.Error(), \"failed to create migration marker\") {\n        return fmt.Errorf(\"fix write permissions on %s, then remove stale markers and retry: %w\", dataDir, err)\n    }\n    return err\n}","preventionTips":["Run migrations as the user that owns the Nomad data directory","Ensure the volume is mounted read-write during migration","Check for stale migration markers after interrupted runs","Verify free disk space before starting a migration"],"tags":["filesystem","permissions","migration","go"],"backgroundTag":"file-write-permission-denied","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}