sentry api silently drops repeated -F flags on GET requests

Open
#1,557 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript
Domain
api, cli

Research direction

Start in packages/cli/src/commands/api.ts with buildQueryParams() and compare its repeated-key handling with buildRawQueryParams(). Read the related GET field cases in packages/cli/test/commands/api.test.ts, then update coverage for repeated -F values and bracket syntax. Done means GET requests preserve intended multi-value parameters and the -F help text accurately explains supported syntax.

Written by the indexing model from the issue text.

Description

What happened

sentry api lets you pass multiple -F key=value flags to select several columns, tags, or fields on a GET request. In practice only the last one survives — every earlier -F with the same key is silently overwritten, with no error or warning. The request goes out with far fewer parameters than the command line implies, and the resulting failure looks completely unrelated to a dropped CLI flag.

This is confusing for a human or an agent following the CLI's own -F key[]=value "array append" help text, because that syntax is real for POST/PUT JSON bodies but does nothing useful for GET query strings — it gets passed through literally as a query key named field[].

Why this is confusing in practice

Two real examples where this cost debugging time:

  1. Selecting multiple log columns with -F 'field[]=timestamp' -F 'field[]=message' -F 'field[]=tags[shard_id,number]' against the logs dataset returned 500 Internal error. Please try again. It looked like the dataset didn't support multi-column or custom-tag selection at all. In reality only the last field was ever sent (the dry-run URL showed a single field%5B%5D=...), so Snuba rejected the under-specified request several layers downstream. Only inspecting --dry-run output revealed the missing fields.
  2. Combining -F 'field=timestamp' -F 'sort=-timestamp' returned "orderby must also be in the selected columns or groupby" even though timestamp was clearly on the command line. The apparent bug looked like broken sort validation — but an earlier repeated -F field=... key had already silently overwritten itself, so the actual selected-columns list sent to the server didn't match what the command line implied.

In both cases the failure surfaces as an opaque server-side error several layers away from the real cause (a CLI flag silently dropped on the client), so the natural next debugging step — "this dataset/parameter must be unsupported" — is wrong and wastes time. Switching from -F to -f (raw field, no JSON parsing) fixed both cases, since -f already merges repeats into an array.

Root cause

Root cause is in packages/cli/src/commands/api.ts:

  • buildQueryParams() (used for -F key=value on GET requests) never merges repeated identical keys into an array — each call just does result[key] = value, so only the last -F field=x survives. This differs from buildRawQueryParams() (-f), which already merges repeats into string[].
  • Bracket-array syntax (key[]=value, documented in the -F help text as "Array append: {key: [value]}") is only implemented for the JSON-body path (parseFields/setNestedValue, used for POST/PUT). For GET requests, key[] is passed through literally as the string "field[]" with no stripping or special handling.
  • The only tested way to send a multi-value GET param today is a single -F 'field=["a","b"]' JSON-array value (see packages/cli/test/commands/api.test.ts).

Net effect: sentry api ORG/PROJECT/events/ -F field[]=timestamp -F field[]=message (or repeating -F field=x without brackets) silently sends a single query param literally named field[] with only the last value — not field=timestamp&field=message. Downstream, Sentry's Django request.GET.getlist("field") never matches field[], so the request resolves to zero selected columns. Against the ourlogs/logs dataset this surfaced as an opaque 500 Internal error. Please try again. (tracked separately in getsentry/sentry as SnubaRPCError: code: 400 — At least one column must be specified in the request, sentry.sentry.io issue 6683878692).

The -F help text presents key[]=value as a uniform rule for all requests, with no callout that it only applies to JSON request bodies, not GET query strings.

Proposed fixes

  • Make buildQueryParams() merge repeated identical -F field=x values into a real array/repeated query param, matching buildRawQueryParams()'s existing behavior.
  • Either support key[]=value bracket syntax for GET query building (stripping the brackets and merging into a repeat), or make it a validation error with a clear message instead of silently producing a mismatched literal field[] param.
  • Update the -F/--field help text to clarify that key[]=value array-append semantics are body-only; document the correct GET multi-value syntax (repeat -F field=x, or a JSON-array value).

via lorenzo.

--

View Junior Session [Sentry]

Dominant language
TypeScript
Stars
121
Forks
14
Avg merge
22h 3m
Merged PRs (30d)
94

Contributor guide

No contributing guide indexed for this repository

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 getsentry/cli

All issues in getsentry/cli

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.