Hit this on lash 0.4.0 while linting fixture-site: lash lint crashes with exit 101 instead of reporting its findings.
ERROR Panic occurred location=crates/lash-types/src/task.rs:222:40 end byte index 57 is not a char boundary; it is inside '—' (bytes 55..58 of string)
The trigger is a contextual note that is long enough for W_NOTE_TOO_LONG (over 200 chars) and happens to have a multi-byte character straddling byte 57. Rendering the warning calls ContextualNote::truncated_text(60), which slices by bytes:
format!("{}...", &self.text[..max_len - 3])
&self.text[..57] panics whenever byte 57 falls inside a multi-byte char. An em dash at bytes 55..58 does it, so does any accented letter or CJK char at that position.
Minimal repro, two files in an empty directory:
lash.index.md
# Index
- [Repro](tasks.repro.md)
tasks.repro.md (the note is 55 a's, an em dash, then enough padding to pass 200 chars)
# Repro
@id: repro
## Tasks
- [ ] a task
## Implementation notes
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa— trailing text bbbb…(pad past 200 chars)…bbbb
Then lash index && lash lint crashes with the panic above.
Fix is to truncate on a char boundary, floor_char_boundary once it stabilizes, or walk back with is_char_boundary, or take chars instead of bytes. Worth a quick audit for other byte-index slicing on user text while in there, any truncation helper has the same exposure.
In any case, the workaround is easy once you spot it (reword the note so no multi-byte char sits at byte 55..58), it just presents as lint crashing on a file that looks fine.
Hit this on lash 0.4.0 while linting fixture-site:
lash lintcrashes with exit 101 instead of reporting its findings.The trigger is a contextual note that is long enough for W_NOTE_TOO_LONG (over 200 chars) and happens to have a multi-byte character straddling byte 57. Rendering the warning calls
ContextualNote::truncated_text(60), which slices by bytes:&self.text[..57]panics whenever byte 57 falls inside a multi-byte char. An em dash at bytes 55..58 does it, so does any accented letter or CJK char at that position.Minimal repro, two files in an empty directory:
lash.index.mdtasks.repro.md(the note is 55 a's, an em dash, then enough padding to pass 200 chars)Then
lash index && lash lintcrashes with the panic above.Fix is to truncate on a char boundary,
floor_char_boundaryonce it stabilizes, or walk back withis_char_boundary, or take chars instead of bytes. Worth a quick audit for other byte-index slicing on user text while in there, any truncation helper has the same exposure.In any case, the workaround is easy once you spot it (reword the note so no multi-byte char sits at byte 55..58), it just presents as lint crashing on a file that looks fine.