{"record":{"id":"5aedc398395873f4","repo":"chenhg5/cc-connect","slug":"heartbeat-timed-out-after-v","errorCode":null,"errorMessage":"heartbeat timed out after %v","messagePattern":"heartbeat timed out after (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/heartbeat.go","lineNumber":372,"sourceCode":"\t\tprompt = readHeartbeatMD(entry.workDir)\n\t}\n\tif prompt == \"\" {\n\t\tprompt = defaultHeartbeatPrompt\n\t}\n\n\tslog.Info(\"heartbeat: executing\", \"project\", entry.project, \"session_key\", cfg.SessionKey, \"prompt_len\", len(prompt))\n\n\ttimeout := time.Duration(cfg.TimeoutMins) * time.Minute\n\tdone := make(chan error, 1)\n\tgo func() {\n\t\tdone <- entry.engine.ExecuteHeartbeat(cfg.SessionKey, prompt, cfg.Silent)\n\t}()\n\n\tvar err error\n\tselect {\n\tcase err = <-done:\n\tcase <-time.After(timeout):\n\t\terr = fmt.Errorf(\"heartbeat timed out after %v\", timeout)\n\t}\n\n\ths.mu.Lock()\n\tentry.runCount++\n\tentry.lastRun = time.Now()\n\tif err != nil {\n\t\tentry.errorCount++\n\t\tentry.lastError = err.Error()\n\t\tslog.Error(\"heartbeat: execution failed\", \"project\", entry.project, \"error\", err)\n\t} else {\n\t\tentry.lastError = \"\"\n\t\tslog.Info(\"heartbeat: execution completed\", \"project\", entry.project)\n\t}\n\ths.mu.Unlock()\n}\n\nconst defaultHeartbeatPrompt = `This is a periodic heartbeat check. Please briefly review:\n- Any pending tasks or unfinished work","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/heartbeat.go#L354-L390","documentation":"The heartbeat execution in core/heartbeat.go runs the entry's task in a goroutine and waits on a done channel with a timeout. If the task does not finish within the configured timeout, the select falls to the time.After branch and the run is failed with this error. The heartbeat task itself keeps running in the background (it is not cancelled), but the run is recorded as failed.","triggerScenarios":"TriggerNow or the periodic run loop executes a heartbeat whose task goroutine takes longer than the entry's timeout; e.g. a hung process check, blocked network call, or deadlock inside the heartbeat handler.","commonSituations":"Heartbeat checks an agent CLI that hangs waiting on stdin; network probe to an unresponsive host without its own deadline; system under heavy load slowing the check past the timeout; timeout configured too aggressively for a normally-slow task.","solutions":["Increase the heartbeat timeout in the entry configuration","Add an internal context deadline to the heartbeat task so it can be cancelled properly","Check what the heartbeat task contacts (process, network) and fix the underlying hang","Inspect system load or deadlocks in the heartbeat handler"],"exampleFix":"// before: no internal deadline, task hangs past timeout\nfunc heartbeat(ctx context.Context) error { return checkAgent() }\n// after\ndefCtx, cancel := context.WithTimeout(ctx, 20*time.Second)\ndefer cancel()\nfunc heartbeat(ctx context.Context) error { return checkAgentWithContext(ctx) }","handlingStrategy":"retry","validationCode":"// estimate task duration before registering\ndur := measureHeartbeatTask()\nif dur > timeout { return fmt.Errorf(\"task (%s) exceeds timeout (%s)\", dur, timeout) }","typeGuard":null,"tryCatchPattern":"if err := hb.TriggerNow(name); err != nil {\n    if strings.Contains(err.Error(), \"timed out after\") {\n        slog.Warn(\"heartbeat timed out; task may still be running\", \"err\", err)\n        // backoff and retry on next tick\n    }\n}","preventionTips":["Give every heartbeat task an internal context deadline shorter than the entry timeout","Set timeouts generously relative to observed task duration","Avoid blocking network calls without deadlines inside heartbeat handlers","Alert on repeated timeout errors — they indicate a hang, not slowness"],"tags":["timeout","heartbeat","health-check"],"backgroundTag":"request-timeout","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}