Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

GitHub connector update_ref rejects advertised expected_sha argument with InvalidActionArgumentsError

Open Beginner friendly
#50,987 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
github, rust

Research direction

Locate the GitHub connector's update_ref action schema in the tool discovery layer and the runtime action binder that processes its arguments. Either implement expected_sha using GitHub's GraphQL updateRefs mutation with beforeOid, or remove it from the advertised schema so both layers agree. Run the connector tests to confirm update_ref no longer rejects the argument unexpectedly.

Written by the indexing model from the issue text.

Description

bug tool-calls

Summary

The GitHub connector currently advertises an optional expected_sha argument on its update_ref action, apparently intended to provide expected-head / force-with-lease-style protection.

However, calls that include expected_sha are rejected during connector argument processing with:

INVALID_ARGUMENT
InvalidActionArgumentsError

The branch ref is not modified.

Calling the same update_ref action without expected_sha succeeds.

This appears to be a schema/runtime mismatch in the GitHub connector: tool discovery exposes expected_sha, but the deployed action binder does not accept it.

Environment

  • Surface: ChatGPT web
  • Connector: OpenAI GitHub connector
  • Operation: update_ref
  • Reproduced: 2026-10-04
  • Repository type: normal writable GitHub repository
  • Ref update type: branch fast-forward to a newly created Git commit
  • force: false

The issue was reproduced during a normal Git-data workflow using:

create_blob
→ create_tree
→ create_commit
→ update_ref

Advertised action contract

The connector currently exposes update_ref with arguments equivalent to:

repository_full_name
branch_name
sha
force
expected_sha

expected_sha is described as the expected current branch HEAD, providing lease / expected-head protection.

That makes the following operation appear supported:

update_ref(
    branch_name = "feature-branch",
    sha = NEW_COMMIT,
    force = false,
    expected_sha = CURRENT_HEAD
)

Actual behavior

Including expected_sha causes the connector call to fail before the branch ref is updated:

INVALID_ARGUMENT
InvalidActionArgumentsError

After the rejected call, the branch HEAD was explicitly reread and confirmed to be unchanged.

Removing only the expected_sha argument allows the update to succeed:

update_ref(
    branch_name = "feature-branch",
    sha = NEW_COMMIT,
    force = false
)

The branch then advances to the requested commit normally.

Minimal reproduction

Starting state:

branch HEAD = A

Create a new Git commit whose parent is exactly A:

A
└── C

Then call the connector action with:

repository_full_name = <repository>
branch_name = <branch>
sha = C
force = false
expected_sha = A
Observed result
INVALID_ARGUMENT
InvalidActionArgumentsError

Branch remains at:

A

Retry the same operation without expected_sha:

repository_full_name = <repository>
branch_name = <branch>
sha = C
force = false
Observed result

Successful ref movement:

A → C

Expected behavior

One of these should be true:

  1. expected_sha is supported as advertised and the connector performs an atomic expected-head update; or
  2. expected_sha is not supported and should not appear in the exposed action schema.

The current state is dangerous for tool consumers because the advertised schema implies stronger concurrency semantics than the runtime actually provides.

A caller cannot determine from tool discovery alone that the argument will fail.

Why this does not appear to be a GitHub REST API error

GitHub's REST "Update a reference" endpoint accepts the target SHA and a force flag.

It does not expose an expected_sha request parameter.

Therefore expected_sha appears to be an OpenAI connector abstraction rather than a direct GitHub REST parameter.

The failure also occurs as InvalidActionArgumentsError, and no branch movement occurs, which is consistent with rejection during connector argument binding rather than a rejected GitHub ref update.

Recommended implementation

GitHub's GraphQL API already exposes the exact primitive needed for this behavior.

The updateRefs mutation supports RefUpdate with:

name
beforeOid
afterOid
force

beforeOid requires the ref to point at the specified object before the update is performed.

The connector could therefore implement:

expected_sha → beforeOid
sha          → afterOid
branch_name  → name
force        → force

Conceptually:

updateRefs(
  refUpdates: [{
    name: "refs/heads/feature-branch"
    beforeOid: EXPECTED_SHA
    afterOid: NEW_SHA
    force: false
  }]
)

GitHub performs updateRefs atomically, so this would provide true compare-and-swap / expected-head semantics without a client-side read-check-write race.

Why the current workaround is insufficient as a general solution

For ordinary append-only commits, callers can use:

known HEAD A
→ create commit C with parent A
→ update_ref(C, force=false)

A normal concurrent branch advance will generally cause the update to become non-fast-forward and GitHub will reject it.

That is a useful fallback, but it is not equivalent to true expected-head semantics.

It does not fully cover cases such as:

  • force rewrites;
  • arbitrary ref movement;
  • moving to an already-existing descendant;
  • shared branches with unusual concurrent mutation;
  • destructive or administrative ref operations.

Those cases need actual compare-and-swap semantics such as beforeOid, or an equivalent force-with-lease implementation.

Additional concern: advertised capability vs runtime capability

This also appears to fit a broader class of connector defects where tool discovery and runtime argument binding are temporarily out of sync.

For agentic workflows, this is particularly costly because an executor may:

  1. discover the schema;
  2. design its concurrency strategy around the advertised argument;
  3. create blobs, trees, and commits;
  4. reach the final ref mutation;
  5. discover only then that the advertised argument is rejected.

At minimum, tool discovery and the deployed action implementation should agree on the accepted arguments.

Suggested resolution

Preferred:

  • implement expected_sha using GitHub GraphQL updateRefs.beforeOid.

Acceptable interim fix:

  • remove expected_sha from the exposed update_ref schema until the runtime supports it.

It would also be useful for the action to distinguish an expected-head mismatch from malformed arguments, for example with a dedicated conflict/lease error rather than InvalidActionArgumentsError.

Impact

This affects automated Git workflows that want to perform one logical multi-file mutation as:

create blobs
→ create tree
→ create commit
→ atomically advance branch if HEAD is unchanged

Without working expected-head semantics, callers either have to:

  • add redundant branch rereads around ref movement;
  • rely only on non-fast-forward protection;
  • switch to another Git execution surface for lease-protected mutations.

That increases connector round trips and makes safe high-throughput repository automation harder than necessary.

The existing action schema already appears designed to solve this problem; the runtime simply does not currently honor the advertised argument.

Dominant language
Rust
Stars
128k
Forks
20.1k
Avg merge
1m
Merged PRs (30d)
994

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.