angular/angular · error · RuntimeError

JSONP_WRONG_RESPONSE_TYPE

JSONP_WRONG_RESPONSE_TYPE

Error message

JSONP requests must use Json response type.

What it means

Thrown by JsonpClientBackend.handle when a request with method 'JSONP' arrives with a responseType other than 'json'. A JSONP response is executed as a JavaScript script that passes a value to a callback, so 'text', 'arraybuffer', 'blob', or 'body' response types are physically impossible over JSONP. The check runs before any script tag is created, as a guard against improperly routed or hand-built requests.

Source

Thrown at packages/common/http/src/jsonp.ts:139

    return `ng_jsonp_callback_${nextRequestId++}`;
  }

  /**
   * Processes a JSONP request and returns an event stream of the results.
   * @param req The request object.
   * @returns An observable of the response events.
   *
   */
  handle(req: HttpRequest<never>): Observable<HttpEvent<any>> {
    // Firstly, check both the method and response type. If either doesn't match
    // then the request was improperly routed here and cannot be handled.
    if (req.method !== 'JSONP') {
      throw new RuntimeError(
        RuntimeErrorCode.JSONP_WRONG_METHOD,
        ngDevMode && JSONP_ERR_WRONG_METHOD,
      );
    } else if (req.responseType !== 'json') {
      throw new RuntimeError(
        RuntimeErrorCode.JSONP_WRONG_RESPONSE_TYPE,
        ngDevMode && JSONP_ERR_WRONG_RESPONSE_TYPE,
      );
    }

    // Check the request headers. JSONP doesn't support headers and
    // cannot set any that were supplied.
    if (req.headers.keys().length > 0) {
      throw new RuntimeError(
        RuntimeErrorCode.JSONP_HEADERS_NOT_SUPPORTED,
        ngDevMode && JSONP_ERR_HEADERS_NOT_SUPPORTED,
      );
    }

    if (!this.isAllowedJsonpUrl(req.urlWithParams)) {
      throw new RuntimeError(RuntimeErrorCode.JSONP_UNSAFE_URL, ngDevMode && JSONP_ERR_UNSAFE_URL);
    }

View on GitHub (pinned to 51cb07e980)

Solutions

  1. Use responseType 'json' (the default) for any JSONP request, or just call HttpClient.jsonp(url, callback) which sets it correctly
  2. If you need text/blob/arraybuffer bodies, use a normal http.get()/http.post() over XHR or fetch instead of JSONP
  3. Audit interceptors that clone requests with responseType overrides and skip or fix them for method === 'JSONP'
  4. Prefer migrating off JSONP entirely (it is deprecated) to standard CORS-enabled requests

Example fix

// before
const req = new HttpRequest('JSONP', 'https://api.example.com/data', null, {
  responseType: 'text', // JSONP can only deliver JSON
});
http.request(req).subscribe();

// after
http.jsonp<unknown>('https://api.example.com/data', 'callback').subscribe();
// or, for non-JSON payloads, a normal request:
http.get('https://api.example.com/data', {responseType: 'text'});
Defensive patterns

Strategy: validation

Validate before calling

function assertJsonpCompatible(req: HttpRequest<unknown>): void {
  if (req.method === 'JSONP' && req.responseType !== 'json') {
    throw new Error(`JSONP request to ${req.url} must use responseType 'json'`);
  }
}
// run before handing the request to HttpClient / an interceptor chain

Type guard

type JsonpRequest = HttpRequest<never> & {method: 'JSONP'; responseType: 'json'};
function isJsonpRequest(req: HttpRequest<unknown>): req is JsonpRequest {
  return req.method === 'JSONP' && req.responseType === 'json';
}

Try / catch

try {
  http.jsonp<unknown>(url, 'cb').subscribe(next, done);
} catch (err) {
  // backend validation errors throw synchronously at the HttpClient call site
  if (err instanceof Error && /JSONP/.test(err.message)) { /* fix request config */ }
  else throw err;
}

Prevention

When it happens

Trigger: Hand-constructing an HttpRequest with method 'JSONP' and a non-json responseType (e.g. new HttpRequest('JSONP', url, {responseType: 'text'})) and letting the JsonpInterceptor route it to JsonpClientBackend; or cloning a JSONP request in an interceptor with a changed responseType.

Common situations: Copying a request-building helper that defaults responseType: 'text'; an interceptor that clones requests and overrides responseType; migrating a normal GET to JSONP while keeping its options object. Note JSONP itself is deprecated since Angular 22.1 due to XSS risk.

Related errors


AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22). Data as JSON: /api/errors/96b1071d403c6512. Report an issue: GitHub.