wavetermdev/waveterm · error

failed to unmarshal backup metadata: %w

Error message

failed to unmarshal backup metadata: %w

What it means

RestoreBackup parses the metadata sidecar into BackupMetadata with json.Unmarshal. This error wraps unmarshal failure, meaning the .json content is not valid JSON for the expected schema (or was truncated/corrupted) and the restore is aborted.

Source

Thrown at pkg/filebackup/filebackup.go:105

	return backupPath, nil
}

func RestoreBackup(backupFilePath string, restoreToFileName string) error {
	backupData, err := os.ReadFile(backupFilePath)
	if err != nil {
		return fmt.Errorf("failed to read backup file: %w", err)
	}

	metadataPath := backupFilePath[:len(backupFilePath)-4] + ".json"
	metadataData, err := os.ReadFile(metadataPath)
	if err != nil {
		return fmt.Errorf("failed to read backup metadata: %w", err)
	}

	var metadata BackupMetadata
	err = json.Unmarshal(metadataData, &metadata)
	if err != nil {
		return fmt.Errorf("failed to unmarshal backup metadata: %w", err)
	}

	if metadata.FullPath != restoreToFileName {
		return fmt.Errorf("backup metadata mismatch: expected %s, got %s", restoreToFileName, metadata.FullPath)
	}

	var perm os.FileMode
	_, err = fmt.Sscanf(metadata.Perm, "%o", &perm)
	if err != nil {
		return fmt.Errorf("failed to parse file permissions: %w", err)
	}

	err = os.WriteFile(restoreToFileName, backupData, perm)
	if err != nil {
		return fmt.Errorf("failed to restore file: %w", err)
	}

	return nil

View on GitHub (pinned to a4447c1563)

Solutions

  1. Validate the .json file content (e.g. jq . metadata.json) to see the syntax error.
  2. Delete the corrupted backup pair and restore from a different backup of the same file in another dated directory.
  3. Avoid hand-editing metadata sidecars; if inspection is needed, copy the file first.
  4. Check the volume for filesystem corruption if multiple sidecars are corrupted.

Example fix

// before
{ "fullpath": "/home/u/f.txt", "timestamp": ... // truncated
// after
delete the corrupt pair and pick another .bak/.json pair for the same file
Defensive patterns

Strategy: validation

Validate before calling

metaData, err := os.ReadFile(strings.TrimSuffix(backupFilePath, ".bak") + ".json")
if err == nil {
    var probe map[string]any
    if json.Unmarshal(metaData, &probe) != nil {
        return fmt.Errorf("metadata sidecar is corrupt/invalid JSON")
    }
}

Try / catch

err := filebackup.RestoreBackup(backupPath, targetPath)
if err != nil {
    if strings.Contains(err.Error(), "unmarshal backup metadata") {
        return fmt.Errorf("backup metadata corrupted, pick another backup: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: The .json sidecar is empty, truncated (e.g. from a crash mid-write), corrupted by an editor, or hand-edited into invalid JSON.

Common situations: System crash/power loss between WriteFile start and completion; manual inspection/edit of the metadata file that broke syntax; file corruption on disk.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/8a8b563de96665ff. Report an issue: GitHub.