{"record":{"id":"7cfa29d5f5794aa9","repo":"nektos/act","slug":"write-back-id-to-db-w","errorCode":null,"errorMessage":"write back id to db: %w","messagePattern":"write back id to db: %w","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"pkg/artifactcache/handler.go","lineNumber":412,"sourceCode":"\t\t\t\tAnd(\"Complete\").Eq(true).\n\t\t\t\tSortBy(\"CreatedAt\").Reverse()); err != nil {\n\t\t\tif errors.Is(err, bolthold.ErrNotFound) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"find cache: %w\", err)\n\t\t}\n\t\treturn cache, nil\n\t}\n\treturn nil, nil\n}\n\nfunc insertCache(db *bolthold.Store, cache *Cache) error {\n\tif err := db.Insert(bolthold.NextSequence(), cache); err != nil {\n\t\treturn fmt.Errorf(\"insert cache: %w\", err)\n\t}\n\t// write back id to db\n\tif err := db.Update(cache.ID, cache); err != nil {\n\t\treturn fmt.Errorf(\"write back id to db: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (h *Handler) useCache(id uint64) {\n\tdb, err := h.openDB()\n\tif err != nil {\n\t\treturn\n\t}\n\tdefer db.Close()\n\tcache := &Cache{}\n\tif err := db.Get(id, cache); err != nil {\n\t\treturn\n\t}\n\tcache.UsedAt = time.Now().Unix()\n\t_ = db.Update(cache.ID, cache)\n}\n","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/artifactcache/handler.go#L394-L430","documentation":"After inserting a cache record, insertCache immediately re-Updates it with bolthold.NextSequence()'s value written back into the record (so the ID field matches the bolt key). This error means the insert succeeded but the follow-up update transaction failed — leaving a half-initialized entry that lookups may not match. Same root causes as insert: lock contention, disk full, corruption.","triggerScenarios":"The two-step insert+update in insertCache (handler.go:406) racing with another writer, or hitting ENOSPC between the insert and update transactions.","commonSituations":"Concurrent cache saves from parallel matrix jobs through one cache server; low-disk CI runners; act crashed between the two transactions on a previous run.","solutions":["Treat the cache entry as not saved: rerun the workflow after clearing lock contention (stop duplicate act runs)","Free disk space on the cache volume","Delete the cache DB if a torn record makes the error repeat","Run cache-heavy matrix jobs with fewer parallel shards"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := insertCache(db, cache); err != nil {\n    if strings.Contains(err.Error(), \"write back id\") {\n        // entry partially persisted; remove it to avoid a torn record\n        _ = db.Delete(cache.ID, cache)\n    }\n    log.Warnf(\"cache save failed: %v\", err)\n}","preventionTips":["Treat insert+write-back as one logical unit; clean up on failure","Avoid concurrent cache saves to the same store","Clear the DB if torn records cause repeat failures"],"tags":["artifact-cache","bolthold","database","concurrency","act"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}