Skip to content

Refuse a locks/batch ref that is not an object with 400 instead of 500 [patch] - #102

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/77-locks-batch-ref-not-object
Oct 9, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/77-locks-batch-ref-not-object

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #77

What was wrong

LockFanOutRequest.TryParse read the ref with root["ref"]?["name"]. When ref is a string, number, bool or array, JsonNode's string indexer throws InvalidOperationException. Nothing in the pipeline caught that exception, so POST locks/batch with "ref": "refs/heads/main" returned an unhandled 500 instead of a 400.

Change

  • A new TryReadRef helper checks that ref is a JsonObject before it reads name. A missing ref is still treated as no ref.
  • A ref that is present but not an object now refuses the whole body. This follows the parser's documented rule that "every malformed shape is refused", so a lock is never taken without the ref the client meant to send.
  • {"ref": {"name": "refs/heads/main"}} behaves exactly as before.

Tests

  • LockFanOutRequestTests adds the first unit tests for LockFanOutRequest. They cover a ref object, an absent ref, and a ref given as a string, number, bool or array. With the fix reverted, all four non-object cases throw InvalidOperationException.
  • LockFanOutTests.RefThatIsNotAnObject_IsRefusedWithoutCallingUpstream checks that the endpoint returns 400 and makes no upstream lock call.

The full suite passes locally: 361 tests, 0 failed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Md2Tr7FWcbqPdwq2BjeG79


Generated by Claude Code

…0 [patch]

LockFanOutRequest.TryParse read the ref with root["ref"]?["name"], and
JsonNode's string indexer throws InvalidOperationException when the node is
a string, number, bool or array. Nothing caught it, so a client that sent
"ref": "refs/heads/main" got an unhandled 500.

The ref is now read with a type check. A ref that is present but not an
object refuses the whole body, matching the parser's rule that every
malformed shape is refused, so a lock is never taken without the ref the
client meant to send.

Fixes #77

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Md2Tr7FWcbqPdwq2BjeG79
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

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.

POST locks/batch returns 500 instead of 400 when ref is not an object (e.g. "ref": "refs/heads/main")

2 participants