github/github-mcp-server · error

provide either 'visible_fields' or 'visible_field_names', no

Error message

provide either 'visible_fields' or 'visible_field_names', not both

What it means

Third guard of validateBlamePath for get_file_blame: the path is split on '/' and rejected if any segment equals "..". This blocks parent-directory traversal before any network call. GitHub's blame would simply find no match for such a path, so the server rejects it locally with 'path must not contain '..' segments'.

Source

Thrown at pkg/github/projects.go:2055

}

func projectViewVisibleFieldsInput(ctx context.Context, gqlClient *githubv4.Client, args map[string]any, owner, ownerType string, projectNumber int) (*ProjectV2ViewConfigurationInput, error) {
	_, hasVisibleFields := args["visible_fields"]
	_, hasVisibleFieldNames := args["visible_field_names"]
	if !hasVisibleFields && !hasVisibleFieldNames {
		return nil, nil
	}

	databaseIDs, err := OptionalBigIntArrayParam(args, "visible_fields")
	if err != nil {
		return nil, err
	}
	names, err := OptionalStringArrayParam(args, "visible_field_names")
	if err != nil {
		return nil, err
	}
	if len(databaseIDs) > 0 && len(names) > 0 {
		return nil, errors.New("provide either 'visible_fields' or 'visible_field_names', not both")
	}
	if len(databaseIDs) == 0 && len(names) == 0 {
		return &ProjectV2ViewConfigurationInput{VisibleFieldIDs: []githubv4.ID{}}, nil
	}

	all, err := listAllProjectFields(ctx, gqlClient, owner, ownerType, projectNumber)
	if err != nil {
		return nil, err
	}

	var resolved []ResolvedField
	if len(names) > 0 {
		resolved, err = resolveFieldsByName(all, owner, projectNumber, names, "visible_fields")
		if err != nil {
			return nil, err
		}
	} else {
		byDatabaseID := make(map[int64]ResolvedField, len(all))

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Resolve and clean the path first, then re-express it relative to the repository root
  2. Reject user input containing '..' before it reaches the tool
  3. Use the final normalized path (e.g. "src/main.go") directly

Example fix

// before
{"owner":"octocat","repo":"Hello-World","path":"docs/../src/main.go"}

// after
{"owner":"octocat","repo":"Hello-World","path":"src/main.go"}
Defensive patterns

Strategy: validation

Validate before calling

func hasTraversal(p string) bool {
	return slices.Contains(strings.Split(p, "/"), "..")
}

Type guard

func isBlamePathError(err error) bool {
	return err != nil && strings.HasPrefix(err.Error(), "path must")
}

Try / catch

if hasTraversal(path) {
	clean, err := filepath.Rel(repoRoot, filepath.Join(repoRoot, path))
	if err != nil || hasTraversal(clean) {
		return nil, fmt.Errorf("unresolvable path: %s", path)
	}
	path = clean
}
res, _, err := callGetFileBlame(ctx, buildArgs(owner, repo, path))

Prevention

When it happens

Trigger: Passing "docs/../src/main.go" or "../other/file.go"; paths produced by filepath.Join with user input containing '..'; normalizing a path that escapes the repository root.

Common situations: Client code combining user-supplied relative paths with '..' components; converting between absolute local paths and repo-relative ones without cleaning; LLM callers echoing filesystem-style paths.

Related errors


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