Skip to content

fix(rcc): guard against None stdout/stderr in plugin validate hook#21

Open
KerryHuang wants to merge 1 commit into
wayne930242:mainfrom
KerryHuang:fix/validate-frontmatter-none-stdio
Open

fix(rcc): guard against None stdout/stderr in plugin validate hook#21
KerryHuang wants to merge 1 commit into
wayne930242:mainfrom
KerryHuang:fix/validate-frontmatter-none-stdio

Conversation

@KerryHuang

Copy link
Copy Markdown

Summary

On Windows, the validate-frontmatter PostToolUse hook surfaces a confusing warning whenever a .claude-plugin/plugin.json or marketplace.json is edited:

⚠ validate-frontmatter [plugins/<name>/.claude-plugin/plugin.json]:
  - plugin validate failed: unsupported operand type(s) for +: 'NoneType' and 'str'

Root cause is in plugins/rcc/hooks/validate_frontmatter.py line 63:

output = (result.stdout + result.stderr).strip()

subprocess.run([\"claude\", \"plugin\", \"validate\", ...], capture_output=True, text=True) can return CompletedProcess with stdout=None / stderr=None on Windows when claude is launched via the npm cmd shim and exits before text-mode decoding completes. The None + str concatenation then raises TypeError, which the outer except Exception as e: return [f\"plugin validate failed: {e}\"] (lines 68–69) surfaces to the user.

The actual claude plugin validate invocation succeeds (exit 0) — it's the post-processing in the hook that breaks.

Fix

One-line defensive change: coerce None to \"\" before concatenation.

output = ((result.stdout or \"\") + (result.stderr or \"\")).strip()

Behavior is unchanged when both streams are strings (the common case on Linux/macOS).

Reproduction (Windows 11, Claude Code CLI via npm)

  1. Edit any plugin.json version field
  2. Watch hook output — warning appears even though claude plugin validate itself returns 0

After the fix, the hook stays silent when claude CLI produces no parseable output.

Test plan

  • Edit a plugin.json under a clean plugin → no warning
  • Edit a plugin.json that genuinely fails validation → warning still surfaces with real diagnostics
  • macOS/Linux behavior unchanged

🤖 Generated with Claude Code

On Windows, `subprocess.run(["claude", "plugin", "validate", ...])` can
return a CompletedProcess where stdout/stderr are None instead of empty
strings (observed when the claude CLI is invoked via npm/cmd shim and
exits with no captured output before text-mode decoding completes).

The concatenation `result.stdout + result.stderr` then raises
`TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'`,
which the outer try/except surfaces as a warning to the user:

  ⚠ validate-frontmatter [<path>]:
    - plugin validate failed: unsupported operand type(s) for +:
      'NoneType' and 'str'

Coerce both streams to "" before concatenation so the hook stays silent
when claude CLI produces no output. No behavior change when both are
strings.
Copilot AI review requested due to automatic review settings May 12, 2026 03:42
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Windows-specific failure in the validate-frontmatter PostToolUse hook where claude plugin validate can yield CompletedProcess.stdout/stderr as None, causing a TypeError during output concatenation and producing a misleading warning despite a successful validation run.

Changes:

  • Coerce stdout/stderr to empty strings before concatenation to avoid NoneType string operations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +63 to 65
output = ((result.stdout or "") + (result.stderr or "")).strip()
if result.returncode != 0 and output:
return [f"plugin validate: {line}" for line in output.splitlines() if line.strip()]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants