Skip to content

Silent no-op writes: issue_write skips empty title/body, and unknown parameters are dropped #3759

Open

Description

@rafe-walker

Describe the bug

Two input-handling gaps make write calls report success while changing nothing:

  1. Empty strings are treated as "not provided". In issue_write method: update, title: "" and body: "" are skipped, and the call returns success with no change. A body can't be cleared, and an empty title is not refused. update_pull_request with title: "" sends the edit and gets a REST 422 (PullRequest.title (missing_field)), so the two tools behave differently.

  2. Unknown or misspelled parameters are silently dropped. No write tool's input schema sets additionalProperties: false (all 19 write tools in the default toolsets, checked via tools/list), and the typed decode ignores extra keys. Examples:

    • issue_write update with only labelz returns success and changes nothing.
    • delete_file with sha deletes without any check (see the separate delete_file issue).
    • actions_list with per_page (the schema says perPage) uses the default page size.

    update_pull_request with only a misspelled field (titel) does fail, but only because its "No update parameters provided." guard (pullrequests.go:1080) catches the empty update.

Related: #3605 / PR #3630 handle misspelled required names (pull_number vs pullNumber) by adding aliases. This issue is about optional fields, where nothing fails.

Same class on the read side: #3316 (open; pull_request_read silently ignores inapplicable pagination params; PRs #3317 and #3336). The *Provided flags for labels/assignees came from #2596 / PR #2600.

Code (main 99d6d65, unchanged since v2.1.0): pkg/github/issues.go:3415-3421 (if title != "" / if body != ""); labels and assignees already use explicit "provided" flags (:3423). Write-tool input schemas have no AdditionalProperties set.

Affected version

v2.1.0 (image sha256:f6056fc1…0f8a, commit 4bcdcdf) and main nightly (image sha256:48bc16d0…338f, revision 99d6d65).

Steps to reproduce the behavior

  1. Issue N has title T, body B, labels [c, d].
    (123 stands for the issue/PR number.)
  2. Call:
    {"name":"issue_write","arguments":{"method":"update","owner":"OWNER","repo":"REPO","issue_number":123,"body":""}}
    Result: OK {"id":"…","url":".../issues/N"}. The body is still B.
  3. Same with "title":"". Result: OK, and the title is still T.
  4. Call:
    {"name":"issue_write","arguments":{"method":"update","owner":"OWNER","repo":"REPO","issue_number":123,"labelz":["a"]}}
    Result: OK, and the labels are still [c, d].
  5. For comparison, update_pull_request {"pullNumber":P,"title":""} returns failed to update pull request: Validation Failed PullRequest.title (missing_field).

Expected vs actual behavior

Expected:

  • An empty body clears the body. An empty title is rejected with a clear message.
  • An unknown parameter is rejected and named (unknown parameter "labelz"), so the caller can correct it.

Actual: success with no change in each case, so an agent believes the update happened.

Suggested fix: decide presence by key, not by value, for title/body (as LabelsProvided already does). Set additionalProperties: false on write-tool input schemas, or reject unknown keys during the typed decode, at least for write tools.

Logs

issue_write update body=""        -> OK {"id":"6277311572","url":".../issues/N"}   body unchanged
issue_write update title=""       -> OK …                                          title unchanged
issue_write update labelz=["a"]   -> OK …                                          labels unchanged
update_pull_request title=""      -> ISERROR failed to update pull request: Validation Failed / PullRequest.title (missing_field)
update_pull_request titel="x"     -> ISERROR No update parameters provided.
tools/list: additionalProperties unset on all 19 write tools (default toolsets)

Same results on v2.1.0 and main. In an earlier run, issue_write method: create with lables also created the issue without labels. That case was not re-run here, to avoid creating issues.

Found during an independent audit of v2.1.0 on a throwaway org and private test repo. Prepared with AI assistance (Claude Code); reproduced by two independent test runs before filing.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions