github/github-mcp-server · error

invalid issue URL %q: %w

Error message

invalid issue URL %q: %w

What it means

issueNumberFromIssueURL extracts everything after the last '/' in a string and runs strconv.Atoi on it. The error fires when that trailing segment is not a bare integer. Callers pass comment.GetIssueURL() — the issue_url field from GitHub's comment API — so failures mean the URL was empty, carried a trailing slash, or had a non-numeric suffix. Notably LastIndex returns -1 on a slash-free string, making Atoi parse the whole input.

Source

Thrown at pkg/github/issues.go:1379

				result = reactionResponse
			default:
				result = commentResponse
			}

			r, err := json.Marshal(result)
			if err != nil {
				return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil
			}

			return utils.NewToolResultText(string(r)), nil, nil
		})
}

func issueNumberFromIssueURL(issueURL string) (int, error) {
	issueNumberString := issueURL[strings.LastIndex(issueURL, "/")+1:]
	issueNumber, err := strconv.Atoi(issueNumberString)
	if err != nil {
		return 0, fmt.Errorf("invalid issue URL %q: %w", issueURL, err)
	}
	return issueNumber, nil
}

// SubIssueWrite creates a tool to add a sub-issue to a parent issue.
func SubIssueWrite(t translations.TranslationHelperFunc) inventory.ServerTool {
	st := NewTool(
		ToolsetMetadataIssues,
		mcp.Tool{
			Name:        "sub_issue_write",
			Description: t("TOOL_SUB_ISSUE_WRITE_DESCRIPTION", "Add a sub-issue to a parent issue in a GitHub repository."),
			Annotations: &mcp.ToolAnnotations{
				Title:        t("TOOL_SUB_ISSUE_WRITE_USER_TITLE", "Change sub-issue"),
				ReadOnlyHint: false,
			},
			InputSchema: &jsonschema.Schema{
				Type: "object",
				Properties: map[string]*jsonschema.Schema{

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Trim trailing slashes and query/fragment before extracting the number
  2. Parse the URL properly with net/url and take the last numeric path segment
  3. If the input is already a bare number, skip URL parsing entirely
  4. Validate with a regexp like ^https?://[^/]+/[^/]+/[^/]+/issues/\d+$ before calling

Example fix

// before
issueNumberString := issueURL[strings.LastIndex(issueURL, "/")+1:]
issueNumber, err := strconv.Atoi(issueNumberString)

// after
u, err := url.Parse(issueURL)
if err != nil {
    return 0, fmt.Errorf("invalid issue URL %q: %w", issueURL, err)
}
seg := strings.Trim(u.Path, "/")
issueNumber, err := strconv.Atoi(seg[strings.LastIndex(seg, "/")+1:])
if err != nil {
    return 0, fmt.Errorf("invalid issue URL %q: %w", issueURL, err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate before calling anything that derives a number from a URL
var issueURLRe = regexp.MustCompile(`^https?://[^/]+/[^/]+/[^/]+/issues/(\d+|)$`)
func isValidIssueURL(u string) bool {
    u = strings.TrimRight(u, "/?#")
    return issueURLRe.MatchString(strings.TrimSuffix(u, "/") + "/") || regexp.MustCompile(`^\d+$`).MatchString(u)
}

Type guard

var issueNumRe = regexp.MustCompile(`/(?:issues)/(\d+)(?:[/?#].*)?$`)
func issueNumberFromURL(u string) (int, bool) {
    m := issueNumRe.FindStringSubmatch(u)
    if m == nil { return 0, false }
    n, err := strconv.Atoi(m[1])
    return n, err == nil
}

Try / catch

num, err := issueNumberFromIssueURL(rawURL)
if err != nil {
    if n, ok := issueNumberFromURL(strings.TrimRight(rawURL, "/")); ok {
        num = n // recover from trailing slash / fragments
    } else {
        return fmt.Errorf("need an issue URL like .../issues/123: %w", err)
    }
}

Prevention

When it happens

Trigger: issue_url is empty (""); URL has a trailing slash so the last segment is ""; URL ends with a query string or fragment instead of the number; a caller passes a number-less string like "https://github.com/o/r/issues/".

Common situations: API responses where issue_url is unexpectedly absent for deleted/anonymized issues; callers passing hand-built or copy-pasted URLs with trailing slashes; schema changes in comment payloads after GitHub API version bumps.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/534026f8e77151a0. Report an issue: GitHub.