`longest_element': undefined method `last' for nil:NilClass (NoMethodError)
Installed mdless on debian 12 using gem install mdless. gem list|grep mdless shows 2.1.57. Tried to view my 1.7mb .aider.chat.history.md, got this error:
[⠦] Processing .aider.chat.history.md...#<Thread:0x00007fbf22f043d8 /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308 run> terminated with exception (report_on_exception is true):
/var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/array.rb:5:in `longest_element': undefined method `last' for nil:NilClass (NoMethodError)
group_by(&:size).max.last[0]
^^^^^
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/console.rb:69:in `hilite_code'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/console.rb:198:in `block_code'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/converter.rb:346:in `render'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/converter.rb:346:in `block (2 levels) in initialize'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:225:in `execute_job'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308:in `block in run'
/var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/array.rb:5:in `longest_element': undefined method `last' for nil:NilClass (NoMethodError)
group_by(&:size).max.last[0]
^^^^^
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/console.rb:69:in `hilite_code'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/console.rb:198:in `block_code'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/converter.rb:346:in `render'
from /var/lib/gems/3.1.0/gems/mdless-2.1.57/lib/mdless/converter.rb:346:in `block (2 levels) in initialize'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:225:in `execute_job'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308:in `block in run'
Exact piece of text that produces the crash:
if groups:
guacdb.debug_print(f"Group memberships: {', '.join(groups)}")
=======
guacdb.debug_print(f"Successfully created user '{args.name}'")
if groups:
guacdb.debug_print(f"Group memberships: {', '.join(groups)}")
>>>>>>> REPLACE
````
gcmanager.py
````python
<<<<<<< SEARCH
guacdb.delete_existing_user(args.username)
guacdb.debug_print(f"Successfully deleted user '{args.username}'")
=======
guacdb.delete_existing_user(args.name)
guacdb.debug_print(f"Successfully deleted user '{args.name}'")
>>>>>>> REPLACE
````
gcmanager.py
````python
<<<<<<< SEARCH
if guacdb.user_exists(args.username):
=======
if guacdb.user_exists(args.name
I think the ==== signs are throwing it off, as those are interpreted as headlines but they're not properly formatted as such. mdless is designed to work with Markdown, not this kind of output, so I don't see a point in forcing it to. I can add error handling fail more gracefully, though.
This IS Markdown, at least in some special field -- Aider (command line coding via LLM tool) keeps its history in .md file called .aider.chat.history.md. These signs are parts of search/replace format used by LLMs, typically like this:
guacalib/version.py
```python
<<<<<<< SEARCH
VERSION = "0.11"
=======
VERSION = "0.12"
>>>>>>> REPLACE
```
or
tests/test_guacaman.bats
```bats
<<<<<<< SEARCH
[[ "$output" == *"testconn2:"* ]]
[[ "$output" != *"permissions:"* ]]
[[ "$output" != *"- testuser1"* ]]
=======
[[ "$output" == *"testconn2:"* ]]
[[ "$output" != *"permissions:"* ]]
[[ "$output" != *" - testconn2"* ]] # Changed from "- testuser1" to " - testconn2
"
>>>>>>> REPLACE
```
Lately this is fairly common stadard for LLM output, parsed ok by Aider, online interfaces like open-webui, etc. LLMs think they are using Markdown :-)
IMHO there is no need to parse it in any special way, but crash makes viewing impossible at all. If you fix the crash, that would be more than enough.
Seems like those should be in code fences, then. Anything followed by an == in Markdown is a headline, and this format will break. It's not Markdown, at least in any standard sense.
On 2 May 2025, at 10:59, burbilog wrote:
burbilog left a comment (ttscoff/mdless#107)
This IS Markdown, at least in some special field -- Aider (command line coding via LLM tool) keeps its history in .md file called .aider.chat.history.md. These signs are parts of sears/replace format used by LLMs, typically like this:
guacalib/version.py ```python <<<<<<< SEARCH VERSION = "0.11" ======= VERSION = "0.12" >>>>>>> REPLACE ```or
tests/test_guacaman.bats ```bats <<<<<<< SEARCH [[ "$output" == *"testconn2:"* ]] [[ "$output" != *"permissions:"* ]] [[ "$output" != *"- testuser1"* ]] ======= [[ "$output" == *"testconn2:"* ]] [[ "$output" != *"permissions:"* ]] [[ "$output" != *" - testconn2"* ]] # Changed from "- testuser1" to " - testconn2 " >>>>>>> REPLACE ```Lately this is fairly common stadard for LLM output, parsed ok by Aider, online interfaces like open-webui, etc. They think they are using Markdown :-)
IMHO there is no need to parse it in any special way, but crash makes viewing impossible at all. If you fix the crash, that would be more than enough.
-- Reply to this email directly or view it on GitHub: https://github.com/ttscoff/mdless/issues/107#issuecomment-2847576979 You are receiving this because you commented.
Message ID: @.***>
Seems like those should be in code fences, then. Anything followed by an == in Markdown is a headline, and this format will break. It's not Markdown, at least in any standard sense. …
Wait, isn't it code fenced with triple backticks?.. According to https://www.markdownguide.org/extended-syntax/
Many Markdown processors support syntax highlighting for fenced code blocks. This feature allows you to add color highlighting for whatever language your code was written in. To add syntax highlighting, specify a language next to the backticks before the fenced code block.
```json
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
It looks like Aider's output is inside backticks quote fence, specifying python as a language for color output.
Oh! I thought those backticks were added by you, I didn't realize they were in the code. If all of those == lines are contained in code fences, then that may not be the issue. I'll do some testing when I get a chance.
Thanks!
I fiddled with history file more, and found that at some point Aider fails to open backticks and thus these chars happen outside of code. Attached smallest crashing log file.
Ok, so the issue was the mismatched code fences. It was trying to pair
them and the last one had nil content, so when it was attempting to
format code it was passing nil to the longest_element function which
wasn't handling it well. Added a fix for that, try gem install mdless
to get the latest version.
It's not going to display what you're expecting because the markup IS invalid, but it won't error out on it.
-Brett
On 5 May 2025, at 6:53, burbilog wrote:
burbilog left a comment (ttscoff/mdless#107)
I fiddled with history file more, and found that at some point Aider fails to open backticks and thus these chars happen outside of code. Attached smallest crashing log file.
-- Reply to this email directly or view it on GitHub: https://github.com/ttscoff/mdless/issues/107#issuecomment-2850753117 You are receiving this because you commented.
Message ID: @.***>
Ugh, two problems. First, i removed mdless and installed it again,using gem uninstall mdless and gem install mdless, as root. now it does not work as user:
marduk pts/9%id
uid=1000(rm) gid=1000(rm) groups=1000(rm),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev),111(bluetooth),113(lpadmin),117(scanner),129(vboxusers),991(docker),992(ollama),993(incus-admin)
marduk pts/9%mdless invalid.md
/usr/local/bin/mdless:25:in `load': cannot load such file -- /var/lib/gems/3.1.0/gems/mdless-2.1.58/bin/mdless (LoadError)
from /usr/local/bin/mdless:25:in `<main>'
It works as root ok. I think previous version worked as regular user okay... my system is regular debian 12. I noticed the same behaviour on debian 12 remote server, too.
Second, i stumbled into another crash:
marduk pts/10#mdless invalid.md
[⠋] Processing invalid.md...#<Thread:0x0000146531c48290 /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308 run> terminated with exception (report_on_exception is true):
/var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:171:in `block in wrap': undefined method `last_color_code' for nil:NilClass (NoMethodError)
(i.positive? ? l[i - 1].last_color_code : '') + l
^^^^^^^^^^^^^^^^
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `map!'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `with_index'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `wrap'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/console.rb:203:in `block_quote'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/converter.rb:346:in `render'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/converter.rb:346:in `block (2 levels) in initialize'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:225:in `execute_job'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308:in `block in run'
/var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:171:in `block in wrap': undefined method `last_color_code' for nil:NilClass (NoMethodError)
(i.positive? ? l[i - 1].last_color_code : '') + l
^^^^^^^^^^^^^^^^
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `map!'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `with_index'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/colors.rb:170:in `wrap'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/console.rb:203:in `block_quote'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/converter.rb:346:in `render'
from /var/lib/gems/3.1.0/gems/mdless-2.1.58/lib/mdless/converter.rb:346:in `block (2 levels) in initialize'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:225:in `execute_job'
from /var/lib/gems/3.1.0/gems/tty-spinner-0.9.3/lib/tty/spinner.rb:308:in `block in run'
I suspect the mess in the history is because because Aider edits README.md with SEARCH/REPLACE and markdown from README.md got included as part of markdown of history file. Anyway, input file that causes the crash is attached.
BTW, another problem with mdless mdless-2.1.58 that it does not work from regular user if installed system-wide as root (gem install mdless):
%mdless README.md
/usr/local/bin/mdless:25:in `load': cannot load such file -- /var/lib/gems/3.1.0/gems/mdless-2.1.58/bin/mdless (LoadError)
from /usr/local/bin/mdless:25:in `<main>'
It works from root just fine.
%ls -al /var/lib/gems/3.1.0/gems/mdless-2.1.58/bin/mdless
-rwx--x--x 1 root root 435 May 17 02:13 /var/lib/gems/3.1.0/gems/mdless-2.1.58/bin/mdless