{"record":{"id":"7fd552c139dfa442","repo":"nikivdev/code","slug":"invalid-js-update-target","errorCode":null,"errorMessage":"invalid js update target","messagePattern":"invalid js update target","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/deps.rs","lineNumber":266,"sourceCode":"        let root =\n            find_js_workspace_root(&nearest_pkg, &ctx.search_root).unwrap_or(nearest_pkg.clone());\n        let manager = opts.manager.unwrap_or_else(|| detect_manager(&root));\n        let workspace = root != nearest_pkg || is_js_workspace_root(&root);\n\n        Ok(Some(UpdateTarget {\n            root,\n            ecosystem: DepsEcosystem::Js,\n            detail: UpdateTargetDetail::Js { manager, workspace },\n        }))\n    }\n\n    fn build_commands(\n        &self,\n        target: &UpdateTarget,\n        opts: &UpdateDepsOpts,\n    ) -> Result<Vec<PlannedCommand>> {\n        let UpdateTargetDetail::Js { manager, workspace } = target.detail else {\n            bail!(\"invalid js update target\");\n        };\n\n        let mut args = match manager {\n            DepsManager::Pnpm => {\n                let mut args = Vec::new();\n                if workspace {\n                    args.push(\"-r\".to_string());\n                }\n                args.push(\"up\".to_string());\n                if opts.latest {\n                    args.push(\"--latest\".to_string());\n                }\n                args\n            }\n            DepsManager::Bun => {\n                let mut args = vec![\"update\".to_string()];\n                if opts.latest {\n                    args.push(\"--latest\".to_string());","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/deps.rs#L248-L284","documentation":"The JS-specific command planner destructures target.detail expecting UpdateTargetDetail::Js. If the target was classified with a different detail variant (or none), the let-else bails because JS manager commands cannot be built from a non-JS target.","triggerScenarios":"build_commands on the JS planner receives an UpdateTarget whose detail is not UpdateTargetDetail::Js — i.e. target detection classified the manifest as another ecosystem (Rust/Go/Python) or left detail unset, then routed it to the JS planner.","commonSituations":"Mixed-repo detection bug where a package.json target got a generic detail; calling the planner API directly with a hand-constructed UpdateTarget; detection changes after a tool version bump.","solutions":["Fix target detection so package.json manifests produce UpdateTargetDetail::Js { manager, workspace }","Ensure the target is routed to the planner matching its ecosystem, not unconditionally to the JS one","When constructing UpdateTarget manually, always set detail = UpdateTargetDetail::Js with a valid DepsManager"],"exampleFix":"// before\nlet target = UpdateTarget { detail: UpdateTargetDetail::Generic };\nplanner.build_commands(&target, &opts)?  // bails\n\n// after\nlet target = UpdateTarget { detail: UpdateTargetDetail::Js {\n    manager: DepsManager::Npm, workspace: false,\n}};\nplanner.build_commands(&target, &opts)?","handlingStrategy":"type-guard","validationCode":"// verify detail variant before calling the JS planner\nif !matches!(target.detail, UpdateTargetDetail::Js { .. }) {\n    return Err(anyhow!(\"target is not a JS project\"));\n}","typeGuard":"fn is_js_target(t: &UpdateTarget) -> bool {\n    matches!(t.detail, UpdateTargetDetail::Js { .. })\n}","tryCatchPattern":null,"preventionTips":["Route targets to planners by ecosystem, not by planner availability","Always populate detail when constructing UpdateTarget","Cover detection with tests for mixed-ecosystem repos"],"tags":["internal","javascript","dependencies","invariant-violation"],"backgroundTag":"invalid-target-type","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}