Skip to content

fix(sdk): PipeRef.fetch accepts a limit option it silently ignores #464

Description

@EricAndrechek

Area: sdk — silent no-op · found by CodeRabbit on #456

PipeRef.fetch(opts?: RequestOptions) accepts the same per-call options type as the query builder, which carries limit — but it forwards only signal:

// clients/ts/src/pipes.ts:28-37
async fetch(opts?: RequestOptions): Promise<Result<Row[]>> {
  const { data, error } = await request<Row[]>(this._ctx, {
    method: "POST",
    path: `/v1/pipes/${encodeURIComponent(this._name)}`,
    body: this._params ?? {},
    signal: opts?.signal,        // <- opts.limit is never read
  });

So wh.pipe('top_pages').fetch({ limit: 10 }) type-checks, runs, and returns whatever the pipe's own SQL returns. The caller gets no error and no indication the bound was ignored.

The other two implementations of the same signature do honour it — QueryBuilder.fetch (query-builder.ts:141, opts?.limit ?? this._state.limit ?? DEFAULT_LIMIT) and TableRef.fetch (table.ts:63, .limit(opts?.limit ?? 1000)) — so the inconsistency is within one shared type, which is what makes it easy to hit.

Limiting a pipe genuinely requires an operator-defined {{limit}} SQL parameter supplied via wh.pipe(name, params); a client-side row cap isn't something the pipes endpoint offers. So the fix is about the surface, not adding a feature.

Pre-existing, not introduced by #456: origin/main has the identical body with the type spelled FetchOptions. #456 only renamed the type, so it neither caused nor worsened this — filing rather than folding it in, to keep that PR's diff about the HTTP-customization surface.

Options

  1. Give PipeRef.fetch a signal-only parameter type (Pick<RequestOptions, "signal">, or a named AbortOptions). Honest surface; a caller passing limit gets a compile error pointing at the real mechanism. Technically breaking for anyone passing limit today, though it never did anything.
  2. Honour it client-side by truncating the returned rows. Cheap, but invents a semantic the endpoint doesn't have and hides how much work the server did.
  3. Document it only. Weakest — the type still advertises it.

Option 1 looks right, ideally with the JSDoc naming wh.pipe(name, { limit }) as the actual route.

Same class as #280 (QueryBuilder.cacheTTL() is a silent no-op) — worth checking whether any other per-call option is accepted and dropped while someone is in here.

— Filed by Claude Opus 5, via Claude Code

Activity

  1. coderabbitai commented on Aug 12, 2026

    @coderabbitai
    🔗 Related PRs

    #456 - feat(sdk)!: add options.headers, fetchOptions, and fetch [open]


    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. EricAndrechek commented on Aug 12, 2026

    @EricAndrechek
    MemberAuthor

    Being fixed in #456 rather than tracked separately — disregard the "filing rather than folding it in" reasoning above.

    Eric pushed back on that call and was right. #456 renames this exact type and gives it a JSDoc describing it as the options for .fetch(), so it makes the misleading surface more prominent, not less — and the fix is one line in a file that PR already touches, in a PR that already carries a ! breaking marker.

    Landed as option 1: PipeRef.fetch(opts?: Pick<RequestOptions, "signal">), with the JSDoc naming wh.pipe(name, { limit }) as the actual route, plus a @ts-expect-error test so the parameter can't quietly widen back.

    Confirmed there was nothing to forward: internal/api/pipes.go:165 binds the request body as the pipe's parameters through pipes.BindParams, so a row cap exists only where the pipe's own SQL declares one.

    The suggestion in the last paragraph — checking whether any other per-call option is accepted and dropped — is not covered by #456 and is still worth doing; #280 is the other known instance.

    — Claude Opus 5, via Claude Code

  3. moved this from Backlog to In progress in WaveHouse Task Boardon Aug 12, 2026
  4. added 2 commits that reference this issue on Aug 12, 2026
    5337c63
    f65f9a8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/sdkTypeScript SDK (clients/ts/)bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions