{"record":{"id":"295ba1241848702a","repo":"loco-rs/loco","slug":"serveronly-boot-always-builds-a-router","errorCode":null,"errorMessage":"ServerOnly boot always builds a router","messagePattern":"ServerOnly boot always builds a router","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"loco-gen/src/templates/deployment/lambda/lambda.t","lineNumber":67,"sourceCode":"use loco_rs::boot::{create_app, StartMode};\nuse loco_rs::environment::{resolve_from_env, Environment};\n{%- if db %}\nuse migration::Migrator;\n{%- endif %}\nuse {{pkg_name}}::app::App;\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n    let environment: Environment = resolve_from_env().into();\n    let config = App::load_config(&environment).await?;\n    {%- if db %}\n    let boot = create_app::<App, Migrator>(StartMode::ServerOnly, &environment, config).await?;\n    {%- else %}\n    let boot = create_app::<App>(StartMode::ServerOnly, &environment, config).await?;\n    {%- endif %}\n    let router = boot\n        .router\n        .expect(\"ServerOnly boot always builds a router\");\n    run(router).await\n}\n","sourceCodeStart":49,"sourceCodeEnd":70,"githubUrl":"https://github.com/loco-rs/loco/blob/23639d1e360dbc618073642b507d6f8664adbaff/loco-gen/src/templates/deployment/lambda/lambda.t#L49-L70","documentation":"The generated AWS Lambda handler boots the app with StartMode::ServerOnly and then unwraps boot.router with an expect stating 'ServerOnly boot always builds a router'. ServerOnly mode is supposed to always construct the router, so a None here is an internal invariant violation — either the boot failed partially, the app's Hooks::routes returned nothing, or the generated code was edited/uses an incompatible loco version where ServerOnly no longer guarantees a router.","triggerScenarios":"Deploying the lambda template and having create_app::<App>(StartMode::ServerOnly, ...) return a boot struct whose .router is None — e.g. hooks misconfigured so no router is built, a loco version mismatch where the ServerOnly contract changed, or hand-edited generated main/lambda code that altered the boot path.","commonSituations":"Pinning a newer/older loco_rs than the template expects; customizing Hooks::routes or boot logic and accidentally skipping router construction; copy-pasting the lambda template into an app whose boot differs from the scaffolded one; feature flags (e.g. no server feature) changing create_app behavior.","solutions":["Verify loco_rs version matches the generated template's expectation (cargo loco doctor; compare Cargo.lock) and regenerate the deployment with `cargo loco generate deployment`.","Ensure your Hooks::routes implementation returns a valid Routes and app boot is unmodified for ServerOnly mode.","Inspect create_app return: if boot.router can legitimately be None in your version, handle it explicitly instead of unwrapping.","Diff your lambda handler against a freshly generated template to spot accidental edits to the boot sequence.","Enable/configure the server feature so ServerOnly boot actually constructs the router."],"exampleFix":"// before\nlet router = boot\n    .router\n    .expect(\"ServerOnly boot always builds a router\");\n// after\nlet router = boot.router.ok_or_else(|| {\n    anyhow::anyhow!(\"loco ServerOnly boot did not build a router; check Hooks::routes and loco version\")\n})?;","handlingStrategy":"type-guard","validationCode":"// before unwrap\ndebug_assert!(boot.router.is_some(), \"ServerOnly boot must build a router; check loco version and Hooks::routes\");","typeGuard":"fn require_router(boot: Boot) -> axum::Router {\n    match boot.router {\n        Some(r) => r,\n        None => panic!(\"ServerOnly boot returned no router — verify loco_rs version and Hooks::routes\"),\n    }\n}","tryCatchPattern":"let router = match boot.router {\n    Some(r) => r,\n    None => {\n        eprintln!(\"lambda boot: no router built; check loco version and Hooks::routes\");\n        return Err(anyhow::anyhow!(\"no router built during ServerOnly boot\"));\n    }\n};","preventionTips":["Keep loco_rs and the loco CLI versions aligned with the template that generated the handler","Regenerate deployment files after framework upgrades instead of hand-editing","Keep Hooks::routes returning a non-empty Routes for server boots","Diff customized lambda handlers against freshly generated templates after upgrades"],"tags":["rust","loco","lambda","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"23639d1e360dbc618073642b507d6f8664adbaff","analyzedAt":"2026-09-12T01:47:20.769Z","contentChangedAt":"2026-09-12T01:47:20.769Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}