{"record":{"id":"ffe9461c0737569d","repo":"windmill-labs/windmill","slug":"found-duplicate-method-for-route-at-path","errorCode":null,"errorMessage":"Found duplicate {} method, for route at path: {}","messagePattern":"Found duplicate (.+?) method, for route at path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-api-openapi/src/lib.rs","lineNumber":381,"sourceCode":"                    request_type = if route_path.starts_with(\"/run/\") {\n                        RequestType::Async\n                    } else if route_path.starts_with(\"/run_and_stream/\") {\n                        RequestType::SyncSse\n                    } else {\n                        RequestType::Sync\n                    };\n\n                    let methods = if request_type == RequestType::Async {\n                        vec![Method::POST]\n                    } else {\n                        vec![Method::GET, Method::POST]\n                    };\n\n                    (methods, true)\n                }\n                Kind::HttpRoute(HttpRouteConfig { method }) => {\n                    if path_object.get(&method.to_string()).is_some() {\n                        return Err(anyhow!(\n                            \"Found duplicate {} method, for route at path: {}\",\n                            method,\n                            path.route_path\n                        )\n                        .into());\n                    }\n                    request_type = path.request_type.unwrap_or(RequestType::Sync);\n                    (vec![method.to_owned()], false)\n                }\n            };\n\n            for method in methods {\n                let mut method_map = IndexMap::new();\n\n                if let Some(summary) = path.summary.as_ref().filter(|s| !s.is_empty()) {\n                    method_map.insert(\"summary\", Value::String(summary.to_owned()));\n                }\n","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-api-openapi/src/lib.rs#L363-L399","documentation":"generate_paths builds the OpenAPI 'paths' object by iterating registered routes. OpenAPI allows only one entry per (path, HTTP method) pair; when two HttpRoute entries define the same method for the same route path, the generator fails with 'Found duplicate {method} method, for route at path: {}'.","triggerScenarios":"Two router registrations map the same HTTP method+path (after :param -> {param} normalization) to different handlers, e.g. GET /workspaces/:w_id defined twice, and generate_openapi_document -> generate_paths runs.","commonSituations":"A route moved to a different path but the old registration left behind; copy-pasted route handlers; route conflicts revealed only when the spec is generated because the router itself matched one first.","solutions":["Remove or rename one of the duplicate route registrations so each (path, method) pair is unique","Grep the router setup for the reported path and method and reconcile the handlers","If routes belong to feature-flagged modules, ensure only one variant is registered per build"],"exampleFix":"// before\n.get(list_workspaces).get(get_workspace) // same path, duplicate GET\n// after\n.get(get_workspace)","handlingStrategy":"try-catch","validationCode":"// before generating the spec, detect duplicate (path, method) pairs\nlet mut seen = std::collections::HashSet::new();\nfor p in paths {\n    if let Kind::HttpRoute(c) = &p.kind {\n        assert!(seen.insert((p.route_path.clone(), c.method.to_string())),\n            \"duplicate route {} {}\", c.method, p.route_path);\n    }\n}","typeGuard":null,"tryCatchPattern":"match generate_paths(&paths, url) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"Found duplicate\") => {\n        tracing::error!(\"duplicate route registration: {e:#}\");\n        std::collections::HashMap::new() // or abort startup\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep all route registrations in one reviewable module","Search for the reported path+method when adding new handlers","Add a startup test that generates the OpenAPI spec to fail fast on duplicates"],"tags":["openapi","routing","rust"],"backgroundTag":"duplicate-route-definition","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}