A stray "j" ruined my evening
A developer recounts a bewildering bug where seemingly valid links consistently produced 404 errors for recipients, leading to a frustrating debugging journey. The culprit was a subtle interaction between jq's default newline output and how terminal emulators interpret control characters. This story resonates on HN as a classic example of an obscure technical detail causing significant headaches, offering a practical lesson in shell scripting and terminal arcana.
The Lowdown
The author, Miro, shares a perplexing debugging experience with a custom link shortener script named 'shirts linkener'. Initially, the script functioned flawlessly, but issues began arising when friends reported 404 errors on links shared through the system, despite the links working correctly when pasted directly by the author. This led to a deep dive into the unexpected behavior of common command-line tools.
- The custom
bashscript utilizedcurlto interact with a link shortening service,passfor credentials,jqto parse the JSON response, andwl-copyto put the shortened URL on the clipboard. - For months, the script performed as expected, seamlessly shortening URLs and making them ready for pasting.
- The trouble began when sharing links, particularly those hosted on S3, with friends, who frequently reported '404 Not Found' errors.
- The inconsistency of the problem made it difficult to diagnose, as the author could often paste the same link without issue.
- Eventually, a pattern emerged: all problematic URLs inexplicably ended with the character 'j'.
- The root cause was identified as
jq's default behavior of appending a newline character (\n) to its output. Whenwl-copyor certain terminal environments handled this, the newline character was misinterpreted as 'j' (specifically, the ANSI newline delimiter^J). - The solution was to use the
--join-output(or-j) flag withjq, which suppresses the trailing newline, thereby preventing the erroneous 'j' from being appended to the URLs.
This incident served as a profound learning experience for the author, highlighting the intricate and sometimes counter-intuitive ways command-line utilities and terminal emulators interact, and underscoring that even seemingly simple operations can harbor complex, hidden behaviors.