{"record":{"id":"7afc821c79d45edf","repo":"jlcodes99/cockpit-tools","slug":"wakeup-cascade-id-last-status","errorCode":null,"errorMessage":"[Wakeup] 网关轨迹持续错误且未恢复: cascade_id={}, last_status={}, error_code={:?}, message={}","messagePattern":"\\[Wakeup\\] 网关轨迹持续错误且未恢复: cascade_id=(.+?), last_status=(.+?), error_code=(.+?), message=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/modules/wakeup.rs","lineNumber":1619,"sourceCode":"                        cascade_id,\n                        if last_status.is_empty() { \"-\" } else { &last_status },\n                        err.error_code,\n                        err.message,\n                        err.error_message_json.len()\n                    ));\n                }\n                return Err(encode_wakeup_ui_error_payload(&err));\n            }\n\n            sleep_with_cancel(\n                std::time::Duration::from_millis(CLIENT_GATEWAY_POLL_INTERVAL_MS),\n                cancel_rx,\n            )\n            .await?;\n        }\n\n        if let Some(err) = last_running_error {\n            crate::modules::logger::log_error(&format!(\n                \"[Wakeup] 网关轨迹持续错误且未恢复: cascade_id={}, last_status={}, error_code={:?}, message={}\",\n                cascade_id,\n                if last_status.is_empty() { \"-\" } else { &last_status },\n                err.error_code,\n                truncate_log_text(&err.message, 500)\n            ));\n            return Err(encode_wakeup_ui_error_payload(&err));\n        }\n\n        let message = if last_status.is_empty() {\n            \"网关未返回唤醒结果（轨迹中未出现 plannerResponse.modifiedResponse）\".to_string()\n        } else {\n            format!(\"网关未在超时时间内返回唤醒结果，最后状态={}\", last_status)\n        };\n        crate::modules::logger::log_error(&format!(\n            \"[Wakeup] 网关唤醒失败(超时/无结果): cascade_id={}, error={}\",\n            cascade_id, message\n        ));","sourceCodeStart":1601,"sourceCodeEnd":1637,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/modules/wakeup.rs#L1601-L1637","documentation":"During the gateway wakeup cascade, the client polls a status/trajectory endpoint; if errors persist across the trajectory without recovery, it aborts with '[Wakeup] 网关轨迹持续错误且未恢复: cascade_id=..., last_status=..., error_code=..., message=...'. This reports the gateway-side run stuck in an error state — not a client request failure but a persisted remote execution error surfaced with the last known status and error code.","triggerScenarios":"trigger_wakeup_via_client_gateway_once tracks a cascade_id's trajectory; each poll returns an error status/error_code, and after the recovery/retry budget is exhausted last_running_error is still Some, so the function logs and returns this error.","commonSituations":"Remote session failing to start (bad environment, missing sandbox); gateway dependency outage keeping the cascade in error; quota/account limit making every attempt fail; a bug in the requested operation causing deterministic failure; operator restarting services mid-run leaving orphaned cascades.","solutions":["Read error_code and last_status in the message — they identify the remote failure reason","Retry the wakeup later to get a fresh cascade_id; do not reuse the errored cascade","Verify account quota/permissions if the error_code indicates limits or denial","Check gateway/service status for an ongoing outage","Escalate with cascade_id and truncated message to the gateway operators if persistent"],"exampleFix":"// before\nif let Some(err) = last_running_error {\n    crate::modules::logger::log_error(&format!(\n        \"[Wakeup] 网关轨迹持续错误且未恢复: cascade_id={}, last_status={}, error_code={:?}, message={}\", ...));\n// after\nif let Some(err) = last_running_error {\n    crate::modules::logger::log_error(&format!(\n        \"[Wakeup] 网关轨迹持续错误且未恢复: cascade_id={}, last_status={}, error_code={:?}, message={}\", ...));\n    mark_cascade_failed(&cascade_id, &err); // persist for UI + telemetry\n}","handlingStrategy":"try-catch","validationCode":"// Before triggering, check no orphaned/failed cascade exists for this context\nif let Some(prev) = last_cascade_for_context(ctx) {\n    if prev.is_failed() && prev.age() < cooldown {\n        eprintln!(\"previous cascade {} still failing; backing off\", prev.id);\n    }\n}","typeGuard":"struct GatewayTrajectoryError { cascade_id: String, last_status: String, error_code: Option<String>, message: String }\nfn is_persistent_trajectory_error(err: &str) -> bool { err.contains(\"网关轨迹持续错误且未恢复\") }","tryCatchPattern":"match trigger_wakeup_via_client_gateway(req).await {\n    Err(e) if e.contains(\"网关轨迹持续错误且未恢复\") => {\n        let cascade_id = extract_field(&e, \"cascade_id=\");\n        // surface to UI with cascade_id; back off before starting a new cascade\n        report_persistent_failure(cascade_id, &e);\n        schedule_retry_with_backoff(Duration::from_secs(300));\n    }\n    other => handle(other),\n}","preventionTips":["Set a bounded retry budget for trajectory polling and honor it","Apply cooldowns per context so failing cascades are not re-triggered immediately","Persist failed cascade_ids for telemetry and operator escalation","Watch error_code trends to catch quota/permission outages early"],"tags":["gateway","cascade","remote-error","polling"],"backgroundTag":"gateway-remote-execution-error","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}