Summary
Three cascading bugs prevent cross-repo update-issue safe-output operations from working. We discovered these while building a workflow that syncs data from repo A into issues on repo B using gh-aw v0.51.6.
All three bugs had to be worked around before the cross-repo update-issue flow functioned. add-comment is unaffected because it has separate routing logic that uses target-repo from config as the default.
Version: gh-aw v0.51.6
Bug 1: repo field missing from compiled tool schema (CRITICAL)
This is the most impactful bug. The gh aw compile tool schema generator does not include repo as an input parameter for the update_issue tool, even when target-repo is configured. The agent literally cannot set repo because it's not in its tool definition.
The compiled tools.json for update_issue includes these properties:
assignees, body, issue_number, labels, milestone, operation, status, title
repo is NOT included.
Meanwhile, the validation schema (in config.json) DOES include repo:
"repo": { "type": "string", "maxLength": 256 }
And the handler factory (update_handler_factory.cjs) checks for item.repo to route cross-repo:
if (item.repo) {
effectiveContext = { ...context, repo: repoResult.repoParts };
}
This creates a dead path: validation accepts repo, handler routes on repo, but the tool schema never exposes it to the agent.
Workaround: Manually edit the lock file to add repo to the update_issue tool schema properties. This is fragile and overwritten on every gh aw compile.
Bug 2: update_handler_factory doesn't use defaultTargetRepo for routing
Even if Bug 1 is fixed and the agent includes repo, the handler factory only routes cross-repo when item.repo is explicitly set. It does NOT fall back to defaultTargetRepo from config.
// Current behavior in update_handler_factory.cjs:
if (item.repo) {
// Only enters cross-repo path when agent explicitly sets repo
effectiveContext = { ...context, repo: repoResult.repoParts };
}
// If item.repo is missing, defaults to context.repo (workflow's own repo) → 404
Contrast with add_comment: The add_comment handler always resolves the target repo from config, so target-repo: "org/other-repo" works without the agent needing to set anything.
Workaround: Add explicit instructions in the agent prompt to always include the repo field, AND manually patch the tool schema (Bug 1 workaround).
Bug 3: target-repo: "*" wildcard not honored in validation
When target-repo: "*", resolveTargetRepoConfig() sets:
defaultTargetRepo = "*"; // from target-repo config
allowedRepos = new Set(); // empty — config has no allowed_repos key
Then validateRepo("org/other-repo", "*", Set()) runs:
qualifiedRepo === defaultRepo → "org/other-repo" === "*" → false (literal comparison)
isRepoAllowed(qualifiedRepo, allowedRepos) → empty set → false
Error: Repository 'org/other-repo' is not in the allowed-repos list. Allowed: *
Workaround: Set target-repo to the explicit repo (e.g., "org/other-repo") instead of "*".
Reproduction
-
Create two repos: org/source-repo (runs the workflow) and org/target-repo (has the issue to update).
-
Configure a workflow in org/source-repo:
safe-outputs:
github-token: ${{ secrets.CROSS_REPO_TOKEN }}
update-issue:
body:
footer: false
target: "*"
target-repo: "org/target-repo"
max: 5
-
Run gh aw compile — the generated tools.json will NOT include repo in update_issue properties.
-
The agent emits (no repo field because it's not in the tool schema):
{ "type": "update_issue", "issue_number": 42, "operation": "replace-island", "body": "..." }
-
The handler defaults to context.repo (workflow's own repo, org/source-repo) → 404 Not Found because issue 42 doesn't exist there.
-
If you use target-repo: "*" instead of an explicit repo, the wildcard validation rejects the target → "not in the allowed-repos list".
Suggested fixes
Fix 1: Add repo to tool schema when target-repo is configured
In the tool schema generator / compiler, when target-repo is set (especially to "*" or a cross-repo value), include repo as a tool input parameter for update_issue and update_pull_request:
"repo": {
"type": "string",
"description": "Target repository in 'owner/repo' format for cross-repo operations."
}
Fix 2: Use defaultTargetRepo for routing in update_handler_factory
Make the factory consistent with add_comment — always resolve via resolveAndValidateRepo, not just when item.repo is set:
// Always resolve repo (matches add_comment behavior)
const repoResult = resolveAndValidateRepo(item, defaultTargetRepo, allowedRepos, itemTypeName);
if (!repoResult.success) { /* handle error */ }
effectiveContext = { ...context, repo: repoResult.repoParts };
Fix 3: Handle defaultRepo === "*" in validateRepo()
Add at the top of validateRepo():
if (defaultRepo === "*") {
return { valid: true, error: null, qualifiedRepo };
}
Key files involved
actions/setup/js/repo_helpers.cjs — validateRepo(), resolveTargetRepoConfig() (Bug 3)
actions/setup/js/update_handler_factory.cjs — if (item.repo) routing logic (Bug 2)
- Compiler / tool schema generator — tool properties generation (Bug 1)
Impact
Cross-repo update-issue and update-pull-request operations are completely broken out of the box. The workflow run completes as "success" but no updates are applied to the target repo. Three manual workarounds are required to make it function. add-comment is unaffected due to its separate routing logic.
Related
- #19276 — Original issue for
repo/operation fields not consumed
- #19282 — PR that fixed attribution URLs and diagnostics (did not fix these bugs)
Summary
Three cascading bugs prevent cross-repo
update-issuesafe-output operations from working. We discovered these while building a workflow that syncs data from repo A into issues on repo B using gh-aw v0.51.6.All three bugs had to be worked around before the cross-repo
update-issueflow functioned.add-commentis unaffected because it has separate routing logic that usestarget-repofrom config as the default.Version: gh-aw v0.51.6
Bug 1:
repofield missing from compiled tool schema (CRITICAL)This is the most impactful bug. The
gh aw compiletool schema generator does not includerepoas an input parameter for theupdate_issuetool, even whentarget-repois configured. The agent literally cannot setrepobecause it's not in its tool definition.The compiled
tools.jsonforupdate_issueincludes these properties:assignees,body,issue_number,labels,milestone,operation,status,titlerepois NOT included.Meanwhile, the validation schema (in
config.json) DOES includerepo:And the handler factory (
update_handler_factory.cjs) checks foritem.repoto route cross-repo:This creates a dead path: validation accepts
repo, handler routes onrepo, but the tool schema never exposes it to the agent.Workaround: Manually edit the lock file to add
repoto theupdate_issuetool schema properties. This is fragile and overwritten on everygh aw compile.Bug 2:
update_handler_factorydoesn't usedefaultTargetRepofor routingEven if Bug 1 is fixed and the agent includes
repo, the handler factory only routes cross-repo whenitem.repois explicitly set. It does NOT fall back todefaultTargetRepofrom config.Contrast with
add_comment: Theadd_commenthandler always resolves the target repo from config, sotarget-repo: "org/other-repo"works without the agent needing to set anything.Workaround: Add explicit instructions in the agent prompt to always include the
repofield, AND manually patch the tool schema (Bug 1 workaround).Bug 3:
target-repo: "*"wildcard not honored in validationWhen
target-repo: "*",resolveTargetRepoConfig()sets:Then
validateRepo("org/other-repo", "*", Set())runs:qualifiedRepo === defaultRepo→"org/other-repo" === "*"→ false (literal comparison)isRepoAllowed(qualifiedRepo, allowedRepos)→ empty set → falseError:
Repository 'org/other-repo' is not in the allowed-repos list. Allowed: *Workaround: Set
target-repoto the explicit repo (e.g.,"org/other-repo") instead of"*".Reproduction
Create two repos:
org/source-repo(runs the workflow) andorg/target-repo(has the issue to update).Configure a workflow in
org/source-repo:Run
gh aw compile— the generatedtools.jsonwill NOT includerepoinupdate_issueproperties.The agent emits (no
repofield because it's not in the tool schema):{ "type": "update_issue", "issue_number": 42, "operation": "replace-island", "body": "..." }The handler defaults to
context.repo(workflow's own repo,org/source-repo) → 404 Not Found because issue 42 doesn't exist there.If you use
target-repo: "*"instead of an explicit repo, the wildcard validation rejects the target → "not in the allowed-repos list".Suggested fixes
Fix 1: Add
repoto tool schema whentarget-repois configuredIn the tool schema generator / compiler, when
target-repois set (especially to"*"or a cross-repo value), includerepoas a tool input parameter forupdate_issueandupdate_pull_request:Fix 2: Use
defaultTargetRepofor routing inupdate_handler_factoryMake the factory consistent with
add_comment— always resolve viaresolveAndValidateRepo, not just whenitem.repois set:Fix 3: Handle
defaultRepo === "*"invalidateRepo()Add at the top of
validateRepo():Key files involved
actions/setup/js/repo_helpers.cjs—validateRepo(),resolveTargetRepoConfig()(Bug 3)actions/setup/js/update_handler_factory.cjs—if (item.repo)routing logic (Bug 2)Impact
Cross-repo
update-issueandupdate-pull-requestoperations are completely broken out of the box. The workflow run completes as "success" but no updates are applied to the target repo. Three manual workarounds are required to make it function.add-commentis unaffected due to its separate routing logic.Related
repo/operationfields not consumed