{"record":{"id":"e1a78a7833cf1054","repo":"alibaba/open-code-review","slug":"session-id-is-required","errorCode":null,"errorMessage":"session id is required","messagePattern":"session id is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume.go","lineNumber":83,"sourceCode":"\tReviewMode      string             `json:\"reviewMode\"`\n\tDiffFrom        string             `json:\"diffFrom\"`\n\tDiffTo          string             `json:\"diffTo\"`\n\tDiffCommit      string             `json:\"diffCommit\"`\n\tScanPaths       *[]string          `json:\"scanPaths\"`\n\tFilePath        string             `json:\"filePath\"`\n\tOldPath         string             `json:\"oldPath\"`\n\tNewPath         string             `json:\"newPath\"`\n\tFingerprint     string             `json:\"fingerprint\"`\n\tSourceSessionID string             `json:\"sourceSessionId\"`\n\tError           string             `json:\"error\"`\n\tComments        []model.LlmComment `json:\"comments\"`\n\tRunManifest     *RunManifest       `json:\"run_manifest\"`\n}\n\n// SessionFilePath returns the JSONL path for a persisted session.\nfunc SessionFilePath(repoDir, sessionID string) (string, error) {\n\tif sessionID == \"\" {\n\t\treturn \"\", fmt.Errorf(\"session id is required\")\n\t}\n\thome, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"resolve home dir: %w\", err)\n\t}\n\treturn filepath.Join(home, \".opencodereview\", sessionSubDir, encodeRepoPath(repoDir), sessionID+\".jsonl\"), nil\n}\n\n// LoadResumeState replays a previous session JSONL into a fingerprint index. A\n// record that cannot be parsed fails the load: with nothing to arbitrate coverage,\n// a dropped line is indistinguishable from a checkpoint that was never written,\n// and the pair it may have belonged to — a review_item_failed retracting an\n// earlier done record — cannot be reconstructed from the rest of the file.\nfunc LoadResumeState(repoDir, sessionID string) (*ResumeState, error) {\n\treturn loadResumeState(repoDir, sessionID, false)\n}\n\n// LoadReviewResumeState replays a review session, dropping records it cannot","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume.go#L65-L101","documentation":"SessionFilePath validates its inputs before building the JSONL path under ~/.opencodereview/<sessions>/<encoded-repo>; an empty sessionID cannot map to a file, so it fails fast with this sentinel-style error. It is used by LoadComments, LoadSummary, LoadDetail and loadResumeState to locate a persisted session. Hitting it means the caller passed an empty/lost session ID instead of a real one.","triggerScenarios":"Calling SessionFilePath(repoDir, \"\"), or calling any loader (LoadComments/LoadSummary/LoadDetail/loadResumeState) after resume state was never established and the session ID variable defaulted to the empty string.","commonSituations":"Resuming before a first session was ever persisted; a config file or env var that should carry the session ID is empty; parsing code that failed to extract the session ID from a previous run's output and silently stored \"\".","solutions":["Pass a non-empty session ID (the UUID returned when the session was created / printed by the previous run)","Guard the call site: if sessionID == \"\" skip resume instead of calling the loader","Check where the session ID is stored (env/config) and fix the empty value at the source","List existing sessions in ~/.opencodereview/<sessions>/<encoded-repo>/ to find the correct <sessionID>.jsonl"],"exampleFix":"// before\npath, err := session.SessionFilePath(repoDir, sessionID) // sessionID == \"\"\n// after\nif sessionID == \"\" { return errors.New(\"no previous session to resume\") }\npath, err := session.SessionFilePath(repoDir, sessionID)","handlingStrategy":"validation","validationCode":"if sessionID == \"\" {\n    return errors.New(\"no session id available; skip resume or run a new session\")\n}\npath, err := session.SessionFilePath(repoDir, sessionID)","typeGuard":null,"tryCatchPattern":"path, err := session.SessionFilePath(repoDir, sessionID)\nif err != nil {\n    if strings.Contains(err.Error(), \"session id is required\") {\n        log.Printf(\"empty session id: %v\", err)\n    }\n}","preventionTips":["Persist the session ID from the first run before attempting resume","Fail fast on empty IDs at config-parse time instead of at the loader","Keep the session ID in a typed struct so an empty value is explicit"],"tags":["validation","session-persistence","arguments"],"backgroundTag":"missing-required-argument","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}