Fix context is not defined crash in safeoutputs MCP server on create_pull_request#18939
Fix context is not defined crash in safeoutputs MCP server on create_pull_request#18939
context is not defined crash in safeoutputs MCP server on create_pull_request#18939Conversation
…eate_pull_request The getDefaultTargetRepo function in repo_helpers.cjs used the bare `context` global variable without any guard. When the safeoutputs MCP server runs as a standalone Node.js daemon, `context` may not be defined, causing: ReferenceError: context is not defined Fix: - Add process.env.GITHUB_REPOSITORY as a direct env var fallback before context - Guard the context access with typeof check (matching get_base_branch.cjs pattern) - Return empty string when all fallbacks fail (instead of crashing) - Add early descriptive error in resolveAndValidateRepo when default repo is empty Tests: - Add delete process.env.GITHUB_REPOSITORY to beforeEach for proper isolation - Add test: GITHUB_REPOSITORY env var used when context is not defined - Add test: GH_AW_TARGET_REPO_SLUG preferred over GITHUB_REPOSITORY - Add test: empty string returned when no config, env vars, or context - Add test: descriptive error when defaultTargetRepo is empty Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
context is not defined crash in safeoutputs MCP server on create_pull_request
|
@copilot review of this fix is still available if shim.cjs is already loaded |
You're right that The fix remains valuable for two reasons:
No code changes needed. |
There was a problem hiding this comment.
Pull request overview
Fixes a ReferenceError: context is not defined crash in the safe-outputs MCP server by making default target-repo resolution work in standalone daemon mode (non-actions/github-script contexts).
Changes:
- Add
process.env.GITHUB_REPOSITORYfallback and guardcontextaccess ingetDefaultTargetRepo. - Add an early, more actionable error in
resolveAndValidateRepowhen no default target repo can be determined. - Extend Vitest coverage for the new fallback/guard behavior and the new error message.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| actions/setup/js/repo_helpers.cjs | Make default repo resolution resilient when context is unavailable; improve error surfaced when repo can’t be resolved. |
| actions/setup/js/repo_helpers.test.cjs | Add tests for GITHUB_REPOSITORY fallback, context-undefined path, empty default, and new descriptive error. |
Comments suppressed due to low confidence (1)
actions/setup/js/repo_helpers.cjs:121
getDefaultTargetRepocan now return an empty string when no config/env/context sources are available, but the JSDoc still states it returns a repository slug inowner/repoformat. Please update the doc comment (or change the API to returnnull/throw) so callers and type-checking expectations match the new behavior.
// Fall back to GITHUB_REPOSITORY env var (available in standalone daemon mode)
const githubRepo = process.env.GITHUB_REPOSITORY;
if (githubRepo) {
return githubRepo;
}
// Fall back to context repo (only available in github-script or shim-provided context)
if (typeof context !== "undefined" && context.repo?.owner && context.repo?.repo) {
return `${context.repo.owner}/${context.repo.repo}`;
}
return "";
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function resolveAndValidateRepo(item, defaultTargetRepo, allowedRepos, operationType) { | ||
| // Check for empty defaultTargetRepo, which indicates a configuration or environment issue | ||
| if (!defaultTargetRepo) { | ||
| return { | ||
| success: false, | ||
| error: `Unable to determine target repository for ${operationType}. Set GH_AW_TARGET_REPO_SLUG, ensure GITHUB_REPOSITORY is available, or configure target-repo in safe-outputs settings.`, | ||
| }; | ||
| } |
There was a problem hiding this comment.
The new !defaultTargetRepo guard returns an error even when item.repo is explicitly provided. This is a behavior regression for tools/messages that support a repo override (e.g., unassign_from_user in safe_outputs_tools.json), where operations should still be able to proceed (and be validated against allowedRepos) even if the default repo can’t be inferred. Consider only erroring when both the resolved repo (after trimming) is empty and there’s no item.repo, or moving repo selection (itemRepo) before the guard and checking that instead.
This issue also appears on line 112 of the same file.
See below for a potential fix:
// Normalize and trim the default target repo (may be empty if not configured)
const trimmedDefaultTargetRepo = defaultTargetRepo ? String(defaultTargetRepo).trim() : "";
// Determine target repository for this operation, allowing item.repo to override
const rawItemRepo = item && item.repo != null ? String(item.repo).trim() : "";
const itemRepo = rawItemRepo || trimmedDefaultTargetRepo;
// If we still don't have a repo after considering overrides, treat as configuration/environment issue
if (!itemRepo) {
return {
success: false,
error: `Unable to determine target repository for ${operationType}. Set GH_AW_TARGET_REPO_SLUG, ensure GITHUB_REPOSITORY is available, or configure target-repo in safe-outputs settings.`,
};
}
// Validate the repository is allowed
const repoValidation = validateRepo(itemRepo, trimmedDefaultTargetRepo, allowedRepos);
There was a problem hiding this comment.
Fixed in 952f6cb. resolveAndValidateRepo now extracts item.repo first and only errors when both item.repo and defaultTargetRepo are empty, following the suggested pattern. I also updated validateRepo to receive trimmedDefaultTargetRepo and added a test for the item.repo-with-empty-default case.
- resolveAndValidateRepo: check item.repo before failing on empty defaultTargetRepo so cross-repo operations still work when the default repo cannot be inferred (addresses code review comment) - unassign_from_user.test.cjs: clear GITHUB_REPOSITORY and GH_AW_TARGET_REPO_SLUG in beforeEach to prevent CI env leakage - repo_helpers.test.cjs: add test for item.repo with empty default Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Fixed in 952f6cb. Added |
Swap fallback order in getDefaultTargetRepo so context is checked first, GITHUB_REPOSITORY second. This preserves behaviour for all existing tests that set global.context (daemon tests delete context explicitly so GITHUB_REPOSITORY still serves as their fallback), and avoids CI's GITHUB_REPOSITORY=github/gh-aw overriding the global.context mock in every handler test file. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Fixed in b4f2f38. The root cause was that |
context is not definedcrash ingetDefaultTargetRepo(GITHUB_REPOSITORY fallback + typeof guard)resolveAndValidateReporegression: only error when bothdefaultTargetRepoanditem.repoare emptyunassign_from_user.test.cjs: clear env vars in beforeEach (belt-and-suspenders)repo_helpers.test.cjs: add test for item.repo with empty defaultTargetRepoOriginal prompt
This section details on the original issue you should resolve
<issue_title>Bug Report:
safeoutputsMCP server crashes withcontext is not definedoncreate_pull_request</issue_title><issue_description># Bug Report:
safeoutputsMCP server crashes withcontext is not definedoncreate_pull_requestRepository: https://github.com/github/gh-aw
Version: v0.50.6 (
awf_version: v0.23.0,awmg_version: v0.1.5)Severity: High — PR creation silently fails; committed changes are lost when the container exits
Summary
When the agent calls
safeoutputs-create_pull_request, the safeoutputs MCP server crashes with a JavaScriptReferenceError:Because the MCP call never succeeds, nothing is written to the JSONL queue, the
safe_outputsjob has nothing to process, and the branch is never pushed to GitHub. Any commits made inside the AWF Docker container are permanently lost when the container exits.Reproduction
workflow_dispatchthat usessafe-outputs: create-pull-requestsafeoutputs-create_pull_requestRoot Cause Analysis
The safeoutputs MCP server is started as a standalone Node.js daemon by
start_safe_outputs_server.shinside the AWF Docker container. Thecreate_pull_requesthandler references a JavaScript variable namedcontext— which is only injected into the scope ofactions/github-scriptworkflow steps by the Actions runner, and is not available in a standalone daemon process.From the compiled lock file, the agent job environment confirms the dispatch context:
For
workflow_dispatchevents,github.event.pull_requestisnull, so this renders as an empty string. However, the empty PR number is a symptom — the actual crash is thecontextvariable reference inside the daemon.The
safe-output-items.jsonlartifact is 0 bytes, confirming no items were ever enqueued. Thesafe_outputsjob ran successfully but processed nothing, so no branch push occurred.Impact
safe_outputsjob reports success (it processed 0 items with 0 errors), so the workflow conclusion issuccess— making the failure invisible without auditingAffected scenario: Any
workflow_dispatch-triggered workflow that usessafe-outputs: create-pull-request. Likely also affects any non-PR event trigger (scheduled runs, issue comments, etc.).Audit Evidence
agent-stdio.log(run 22501315269):safe-output-items.jsonl: 0 bytes (nothing enqueued)aw_info.json:{ "cli_version": "v0.50.6", "awf_version": "v0.23.0", "engine_id": "copilot", "event_name": "workflow_dispatch" }Expected Behavior
safeoutputs-create_pull_requestshould successfully enqueue a PR creation request in the JSONL queue, which thesafe_outputsjob then processes to push the branch and create the PR on GitHub.Actual Behavior
The safeoutputs MCP daemon crashes with
ReferenceError: context is not definedon everycreate_pull_requestcall when triggered from aworkflow_dispatchevent, silently discarding all agent work.Workaround
Add a bash fallback to the workflow prompt that pushes the branch and creates the PR via
gh pr createwith a PAT whensafeoutputs-create_pull_requestfails:This bypasses the safeoutputs MCP entirely and works because
api.github.comis in the...safeoutputsMCP server crashes withcontext is not definedoncreate_pull_request#18751💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.