{"record":{"id":"50930078d641d551","repo":"jdx/mise","slug":"github-relay-request-denied-or-unavailable","errorCode":null,"errorMessage":"GitHub relay request denied or unavailable","messagePattern":"GitHub relay request denied or unavailable","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"src/github_relay.rs","lineNumber":597,"sourceCode":"        let result = tokio::select! {\n            biased;\n            _ = cancel.cancelled() => Err(eyre::eyre!(\"session ended\")),\n            result = tokio::time::timeout(audit.options.request_timeout, forward(broker, request)) => result.unwrap_or_else(|_| Err(eyre::eyre!(\"request timeout\"))),\n        };\n        let status = result.as_ref().map(|r| r.status().as_u16()).unwrap_or(403);\n        if status >= 400 {\n            audit\n                .denied\n                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);\n        }\n        if audit.options.log_requests && result.is_err() {\n            audit.emit(serde_json::json!({\"event\": \"request\", \"operation\": operation, \"status\": status, \"headers_ms\": started.elapsed().as_millis()}));\n        }\n        match result {\n            Ok(response) => response,\n            // Deliberately never serialize upstream errors, URLs or credentials.\n            Err(_) => Response::builder()\n                .status(403)\n                .body(Body::from(\"GitHub relay request denied or unavailable\"))\n                .expect(\"valid response\"),\n        }\n    }\n\n    async fn forward(broker: Broker, request: Request) -> Result<Response> {\n        let deadline = tokio::time::Instant::now() + broker.audit.options.request_timeout;\n        let operation = broker.audit.operation(&broker.scope, &request);\n        let permit = broker.permits.clone().try_acquire_owned()?;\n        let target = authorize(\n            &broker.scope,\n            request.method().as_str(),\n            request.uri().path().strip_prefix('/').unwrap_or_default(),\n            request.uri().query(),\n        )?;\n        let (parts, body) = request.into_parts();\n        let body = to_bytes(body, 8 * 1024 * 1024).await?;\n        if parts.method != Method::POST && !body.is_empty() {","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/github_relay.rs#L579-L615","documentation":"During CLI help rendering, mise replaces the section between the IDIOMATIC_FILES_START and IDIOMATIC_FILES_END markers in a template with a generated table of idiomatic version files. This error means both markers were found, but the start marker appears after the end marker in the content, so the slice range would be invalid. mise treats this as a broken internal template and aborts rather than rendering garbled help output.","triggerScenarios":"Calling render_idiomatic_version_files (via run) on content where .find(IDIOMATIC_FILES_END) returns a smaller index than .find(IDIOMATIC_FILES_START) + marker length — i.e. the END marker precedes the START marker in the help template.","commonSituations":"Someone edited or reordered the help template so the end marker moved above the start marker; a build step or translation/substitution mangled the template; duplicated markers confusing the .find() first-match lookups.","solutions":["Open src/cli/render_help.rs and check the template content; ensure IDIOMATIC_FILES_START appears strictly before IDIOMATIC_FILES_END","Restore the original ordering of the markers if a merge or edit swapped them","Remove duplicated markers so .find() resolves the intended first occurrences","Run `mise run render` to regenerate help output and confirm the table renders"],"exampleFix":"// before (template content)\n// END idiomatic version files\n...text...\n// START idiomatic version files\n\n// after (template content)\n// START idiomatic version files\n...table inserted here...\n// END idiomatic version files","handlingStrategy":"validation","validationCode":"let start = content.find(START_MARKER).expect(\"start marker missing\");\nlet end = content.find(END_MARKER).expect(\"end marker missing\");\nassert!(start < end, \"idiomatic files markers out of order in template\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep START/END markers adjacent and ordered in help templates","Add a unit test that asserts marker order in the template","Avoid programmatic reordering/translation of template content"],"tags":["internal-invariant","cli","help-rendering"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}