{
  "id": 18502109,
  "title": "Why a Stop Hook JSON Error Came from printf %b",
  "url": "https://urgent.news/2026/11/06/why-a-stop-hook-json-error-came-from-printf-b",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-06T13:06:31.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/orca_forge/why-a-stop-hook-json-error-came-from-printf-b-5aap"
  },
  "original_language": "en",
  "account": "The Stop hook reported an \"Unterminated string\" error due to the printf command’s %b format specifier emitting raw newlines inside a JSON string. This occurred because the hook still used a hardcoded cd path from an earlier environment, causing the count of Git changes to miss staged and untracked files. The error message \"JSON Parse error: Unterminated string\" indicated that the output, although resembling a JSON object, was not valid JSON. To resolve the issue, the hook was modified to generate JSON using Python’s json.dumps function, and its execution location was determined at runtime instead of using a hard-coded cd command. Additionally, the change count was adjusted to include staged and untracked files using git status --porcelain=v1 -z. The revised hook also ensured that the output was valid JSON, even when filenames contained special characters like newlines, quotation marks, backslashes, Japanese text, and spaces.",
  "summary": "📝 Originally published (in Japanese) at forge.workstyle.tech . TL;DR The Stop hook reported Unterminated string because printf with %b emitted a raw newline inside a JSON string. The hook also used a cd path fixed to an earlier environment. Its change count missed staged and untracked files when it checked only git diff --name-only . TL;DR The Stop hook error Hook output looks like a JSON object…",
  "key_points": [
    "Stop hook reported Unterminated string error due to printf %b format",
    "Hook modified to generate JSON using Python’s json.dumps function",
    "Execution location determined at runtime, git status adjusted for change count"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}