{"record":{"id":"f32dcd6c903318d2","repo":"BloopAI/vibe-kanban","slug":"scratch-path-should-be-valid","errorCode":null,"errorMessage":"Scratch path should be valid","messagePattern":"Scratch path should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/services/src/services/events/patches.rs","lineNumber":107,"sourceCode":"                .try_into()\n                .expect(\"Workspace path should be valid\"),\n        })])\n    }\n}\n\n/// Helper functions for creating scratch-specific patches.\n/// All patches use path \"/scratch\" - filtering is done by matching id and payload type in the value.\npub mod scratch_patch {\n    use super::*;\n\n    const SCRATCH_PATH: &str = \"/scratch\";\n\n    /// Create patch for adding a new scratch\n    pub fn add(scratch: &Scratch) -> Patch {\n        Patch(vec![PatchOperation::Add(AddOperation {\n            path: SCRATCH_PATH\n                .try_into()\n                .expect(\"Scratch path should be valid\"),\n            value: serde_json::to_value(scratch).expect(\"Scratch serialization should not fail\"),\n        })])\n    }\n\n    /// Create patch for updating an existing scratch\n    pub fn replace(scratch: &Scratch) -> Patch {\n        Patch(vec![PatchOperation::Replace(ReplaceOperation {\n            path: SCRATCH_PATH\n                .try_into()\n                .expect(\"Scratch path should be valid\"),\n            value: serde_json::to_value(scratch).expect(\"Scratch serialization should not fail\"),\n        })])\n    }\n\n    /// Create patch for removing a scratch.\n    /// Uses Replace with deleted marker so clients can filter by id and payload type.\n    pub fn remove(scratch_id: Uuid, scratch_type_str: &str) -> Patch {\n        Patch(vec![PatchOperation::Replace(ReplaceOperation {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/services/src/services/events/patches.rs#L89-L125","documentation":"This panic comes from an `.expect()` in `Patch::add` (crates/services/src/services/events/patches.rs:107) when the constant JSON pointer `SCRATCH_PATH` (\"/scratch\") fails to convert into a json_patch `PatchOperation` path type. It means the hard-coded RFC-6901 JSON pointer string could not be parsed/validated by the json-patch crate. Because the value is a compile-time constant, in practice this only fires if the json-patch crate version changes its path parsing/validation so that \"/scratch\" is rejected. It is a programming/dependency invariant failure, not a data-driven error.","triggerScenarios":"Calling `Patch::add(&scratch)` when `SCRATCH_PATH.try_into()` fails — practically only after upgrading/switching the json_patch dependency so that \"/scratch\" is no longer a valid `jsonp::Pointer` (e.g. stricter RFC-6901 validation or changed `TryFrom<&str>` impl).","commonSituations":"Version changes of `json-patch`/`jsonp` in Cargo.lock or Cargo.toml after `cargo update`; swapping the patch library for one with a stricter path type; refactoring SCRATCH_PATH into a value that is an invalid JSON pointer (must start with '/').","solutions":["Check the json_patch/jsonp dependency version in Cargo.toml/Cargo.lock; pin to a version whose `Pointer: TryFrom<&str>` accepts \"/scratch\" or run `cargo update -p json-patch` to a compatible version.","Verify SCRATCH_PATH is a valid RFC-6901 pointer (non-empty, starts with '/'); if you changed it, restore `const SCRATCH_PATH: &str = \"/scratch\";`.","If the new library requires a different path construction, build the Pointer via its API (e.g. `Pointer::parse(\"/scratch\")` or builder methods) instead of `try_into()` and handle the Result explicitly.","As a last resort, replace `.expect()` with a lazy static/OnceCell that parses once at startup and surfaces the error loudly there."],"exampleFix":"// before\npath: SCRATCH_PATH.try_into().expect(\"Scratch path should be valid\"),\n// after\nstatic SCRATCH_POINTER: Lazy<Pointer> =\n    Lazy::new(|| Pointer::parse(SCRATCH_PATH).expect(\"SCRATCH_PATH must be a valid JSON pointer\"));\n...\npath: SCRATCH_POINTER.clone(),","handlingStrategy":"validation","validationCode":"// Before constructing add-patches, assert the constant parses on this json_patch version:\nfn assert_scratch_path_valid() {\n    let p: Result<json_patch::Pointer, _> = \"/scratch\".try_into();\n    assert!(p.is_ok(), \"SCRATCH_PATH incompatible with json_patch version\");\n}\n// In tests: #[test] fn scratch_path_is_valid_pointer() { assert_scratch_path_valid(); }","typeGuard":"fn is_valid_pointer(s: &str) -> bool {\n    <json_patch::Pointer as TryFrom<&str>>::try_from(s).is_ok()\n}","tryCatchPattern":"// expect() panics cannot be caught; fail fast in CI instead:\nlet ptr = Pointer::parse(SCRATCH_PATH)\n    .unwrap_or_else(|e| panic!(\"invalid SCRATCH_PATH {SCRATCH_PATH}: {e}\"));","preventionTips":["Add a unit test asserting SCRATCH_PATH converts into the json_patch Pointer type.","Pin json_patch/jsonp versions in Cargo.toml and review their changelogs before `cargo update`.","Never edit SCRATCH_PATH without checking RFC-6901 validity (leading '/', '~'/'/' escaping).","Run `cargo test --workspace` after dependency upgrades."],"tags":["rust","panic","json-patch","serialization"],"backgroundTag":"json-pointer-invalid","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}