{"record":{"id":"bf12b75a59f603c2","repo":"kopia/kopia","slug":"snapshot-source-has-less-than-two-snapshots","errorCode":null,"errorMessage":"snapshot source has less than two snapshots","messagePattern":"snapshot source has less than two snapshots","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/diff/diff.go","lineNumber":459,"sourceCode":"\t\t\treturn snapshotList[i-1], nil\n\t\t}\n\t}\n\n\treturn nil, errors.New(\"couldn't find immediately preceding snapshot\")\n}\n\n// GetTwoLatestSnapshotsForASource fetches two latest snapshot manifests for a given source if they exist.\nfunc GetTwoLatestSnapshotsForASource(ctx context.Context, rep repo.Repository, source snapshot.SourceInfo) (secondLast, last *snapshot.Manifest, err error) {\n\tsnapshots, err := snapshot.ListSnapshots(ctx, rep, source)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"failed to list all snapshots\")\n\t}\n\n\tconst minimumReqSnapshots = 2\n\n\tsizeSnapshots := len(snapshots)\n\tif sizeSnapshots < minimumReqSnapshots {\n\t\treturn nil, nil, errors.New(\"snapshot source has less than two snapshots\")\n\t}\n\n\tsort.Slice(snapshots, func(i, j int) bool {\n\t\treturn snapshots[i].StartTime.Before(snapshots[j].StartTime)\n\t})\n\n\treturn snapshots[sizeSnapshots-2], snapshots[sizeSnapshots-1], nil\n}\n","sourceCodeStart":441,"sourceCodeEnd":468,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/internal/diff/diff.go#L441-L468","documentation":"GetTwoLatestSnapshotsForASource requires at least two snapshots for a source to return the last and second-last manifests. If fewer than two exist, it returns this error since no pair can be returned.","triggerScenarios":"Calling GetTwoLatestSnapshotsForASource for a source with 0 or 1 snapshots.","commonSituations":"First run of a diff/reporting tool on a newly configured source; a source that has only had one backup ever taken.","solutions":["Run another backup to create a second snapshot","Guard the call by counting snapshots via snapshot.ListSnapshots first","Treat the error as 'nothing to compare' and skip the diff","Manually specify two known snapshot IDs using a diff API that takes explicit IDs"],"exampleFix":"// before\nprev, last, err := diff.GetTwoLatestSnapshotsForASource(ctx, rep, source)\n// after\nsnaps, _ := snapshot.ListSnapshots(ctx, rep, source)\nif len(snaps) < 2 {\n    return nil // only %d snapshot(s) exist\n}\nprev, last, err := diff.GetTwoLatestSnapshotsForASource(ctx, rep, source)","handlingStrategy":"validation","validationCode":"snaps, err := snapshot.ListSnapshots(ctx, rep, source)\nif err != nil || len(snaps) < 2 {\n    return nil // fewer than two snapshots\n}","typeGuard":null,"tryCatchPattern":"prev, last, err := diff.GetTwoLatestSnapshotsForASource(ctx, rep, source)\nif err != nil && strings.Contains(err.Error(), \"less than two\") {\n    return nil // nothing to diff yet\n}","preventionTips":["Schedule at least two backups before enabling diff-based reporting","Check snapshot count before comparing","Skip new sources gracefully in batch jobs"],"tags":["snapshots","diff","insufficient-data"],"backgroundTag":"empty-result-set","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}