Skip to content

SessionEnd hooks are killed before completion when running async work #41577

Closed

Description

@jdubya80

Description

SessionEnd hooks that perform any non-trivial async work (e.g., an API call) are killed before they can complete. Claude Code appears to exit the process without waiting for the hook to finish, even when a generous timeout is configured (tested up to 90s).

Reproduction

  1. Configure a SessionEnd hook in settings.json:
{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/session-log.sh",
            "timeout": 90
          }
        ]
      }
    ]
  }
}
  1. The hook script calls claude -p --model haiku to summarize the session transcript (takes ~5s):
#!/bin/bash
set -euo pipefail
INPUT=$(cat)
TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty')
# ... extract condensed transcript with jq ...
SUMMARY=$(echo "$CONDENSED" | claude -p --bare --model haiku "Summarize this session" 2>/dev/null)
# ... write to log file ...
  1. Exit a Claude Code session normally

Expected: The hook runs to completion within the configured 90s timeout, then Claude Code exits.

Actual: Claude Code exits almost immediately. The claude -p subprocess is killed before it can return. Debug logging confirms the script reaches the claude -p call but never reaches the line after it.

Workaround

Detach the heavy work into a background process so it survives parent exit:

nohup bash -c '
  # ... summarization work here ...
' _ "$TRANSCRIPT_PATH" "$SESSION_ID" "$CWD" >/dev/null 2>&1 &
disown
exit 0

This works reliably but means the hook has no way to report errors back to Claude Code, and users need to manage their own timeout (e.g., wrapping the API call in timeout 60).

Suggestion

Either:

  • Wait for SessionEnd hooks to complete (up to the configured timeout) before exiting the process, consistent with how other hook events appear to work
  • Document the limitation that SessionEnd hooks must not rely on completing before the parent exits, and recommend the nohup/disown pattern for async work

Environment

  • Claude Code: latest (CLI)
  • macOS 15 (Darwin 24.6.0)
  • Shell: zsh

Activity

  1. github-actions commented on Mar 31, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. Stop hook timeout does not kill child process tree #24206
    2. Channel plugin subprocesses (bun server.ts) leak across sessions — not killed on session exit #39137
    3. [BUG] SessionEnd hook cancelled with "Request interrupted by user" on Ctrl+C in Version 2.1.72 #32712

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. added
    duplicateThis issue or pull request already exists
    and removed
    bugSomething isn't working
    has reproHas detailed reproduction steps
    platform:macosIssue specifically occurs on macOS
    on Apr 4, 2026
  3. github-actions commented on Apr 4, 2026

    @github-actions

    This issue has been automatically closed as a duplicate of #24206.

    If this is incorrect, please re-open this issue or create a new one.

    🤖 Generated with Claude Code

  4. github-actions commented on Apr 17, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  5. locked as resolved and limited conversation to collaborators on Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions