{"record":{"id":"681b902a1145f31f","repo":"FuelLabs/sway","slug":"invaliddata","errorCode":"InvalidData","errorMessage":"The provided source range is inconsistent!","messagePattern":"The provided source range is inconsistent!","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"sway-types/src/lib.rs","lineNumber":332,"sourceCode":"            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"The source path must be a valid Sway source file!\",\n            ));\n        }\n\n        if !path.as_ref().exists() {\n            return Err(io::Error::new(\n                io::ErrorKind::NotFound,\n                \"The source path must point to an existing file!\",\n            ));\n        }\n\n        Ok(())\n    }\n\n    pub fn validate_range<'a>(mut range: impl Iterator<Item = &'a Range>) -> io::Result<()> {\n        if !range.any(|r| !r.is_valid()) {\n            Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"The provided source range is inconsistent!\",\n            ))\n        } else {\n            Ok(())\n        }\n    }\n\n    pub fn id_from_repr<'a>(bytes: impl Iterator<Item = &'a u8>) -> Id {\n        let bytes: Vec<u8> = bytes.copied().collect();\n\n        *Hasher::hash(bytes.as_slice())\n    }\n\n    pub const fn id(&self) -> &Id {\n        match self {\n            Self::CallFrame(t) => t.id(),\n            Self::TransactionScript(t) => t.id(),","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/sway-types/src/lib.rs#L314-L350","documentation":"sway-types' Context::validate_range checks a CallFrame/TransactionScript range plus all instruction ranges before construction. Range::is_valid() means start <= end by (line, col). However the condition is inverted: `if !range.any(|r| !r.is_valid())` returns this InvalidData error when NO range is invalid — i.e. when every supplied range is consistent — and returns Ok when at least one range is actually inconsistent. As written, the error is a false positive fired by perfectly valid input from CallFrame::new / TransactionScript::new (used by debug-adapter style tooling).","triggerScenarios":"Calling CallFrame::new or TransactionScript::new with a fully consistent set of ranges (frame range plus every instruction range valid) -> Err(InvalidData, \"inconsistent\"); conversely passing at least one inverted range (start after end) -> Ok. Any code path that validates debug context via Context::validate_range hits the false failure.","commonSituations":"Building debugger/DAP tooling on top of sway-types' Context model; writing tests around CallFrame construction that inexplicably fail with \"inconsistent\" for valid data; upgrading sway-types and seeing previously-working constructions reject input.","solutions":["Fix the inverted condition in sway-types (sway-types/src/lib.rs:331): error when `range.any(|r| !r.is_valid())`, not when none is invalid.","Until patched, avoid Context::validate_range / CallFrame::new / TransactionScript::new and validate ranges yourself before constructing these types.","Report/track upstream at FuelLabs/sway so the validation direction is corrected in a release."],"exampleFix":"// before (sway-types/src/lib.rs:330)\nif !range.any(|r| !r.is_valid()) {\n    Err(io::Error::new(io::ErrorKind::InvalidData, \"The provided source range is inconsistent!\"))\n} else { Ok(()) }\n// after\nif range.any(|r| !r.is_valid()) {\n    Err(io::Error::new(io::ErrorKind::InvalidData, \"The provided source range is inconsistent!\"))\n} else { Ok(()) }","handlingStrategy":"try-catch","validationCode":"// validate ranges yourself (correct direction) before constructing the types\nfn ranges_consistent<'a>(ranges: impl Iterator<Item = &'a sway_types::Range>) -> bool {\n    ranges.all(|r| r.is_valid())\n}\nlet ok = ranges_consistent(std::iter::once(&range).chain(program.iter().map(|p| &p.range)));","typeGuard":"fn is_consistent_range(r: &sway_types::Range) -> bool {\n    r.start.line < r.end.line || (r.start.line == r.end.line && r.start.col <= r.end.col)\n}","tryCatchPattern":"match sway_types::Context::validate_range(ranges) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        // known inverted condition: all-valid input is rejected; log and proceed or fail hard\n        tracing::warn!(kind=?e.kind(), \"validate_range rejected input (known inversion bug)\");\n    }\n    result => result,\n}","preventionTips":["Unit-test validate_range with an all-valid set AND an invalid set; the inversion betrays itself immediately.","Pin a sway-types commit where the condition is fixed (or vendor the fix) for debugger tooling.","Never rely on Ok from this function to mean ranges are sane in affected versions."],"tags":["rust","sway","sway-types","logic-bug","validation","debug-adapter","source-map"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}