← Back to InterPlanetary Improvement Proposals
IPIP 513specificationratifiedp2pipfscontent-addressingroutingapi

Routing V1 Returns 200 for Empty Results

The current Delegated Routing V1 HTTP API specification requires servers to return HTTP 404 (Not Found) when no matching records are found for a query. This creates two significant problems: 1. **Browser Console Errors**: When routing queries are made from web browsers and return 404s, browsers log error messages to the console that cannot be prevented programmatically. These error messages confu

No reviews
Unknown·Updated Mar 29, 2026·0 reviews·0 attestations·View source
Collections:IPIPs — Merged

Specification

Summary

Change the Delegated Routing V1 HTTP API server recommendation to return HTTP status code 200 (OK) with empty results instead of 404 (Not Found) when no matching records are found. This improves semantic correctness, prevents unwanted browser console errors, and provides separate guidance for servers and clients - with clients required to handle both response codes for backward compatibility, resiliency, and maximal interoperability with different server implementations.

Motivation

The current Delegated Routing V1 HTTP API specification requires servers to return HTTP 404 (Not Found) when no matching records are found for a query. This creates two significant problems:

  1. Browser Console Errors: When routing queries are made from web browsers and return 404s, browsers log error messages to the console that cannot be prevented programmatically. These error messages confuse users who understandably think something is broken, when in reality an empty result is a normal and expected outcome for many queries.

  2. Semantic Incorrectness: HTTP 404 means "the requested resource does not exist." However, when querying /routing/v1/providers/{cid}, the endpoint itself exists and is functioning correctly - it simply found no results. Returning 404 conflates "endpoint not found" with "no data found," which are fundamentally different conditions.

As noted in the original issue, querying for a peer with specific filters demonstrates this problem clearly:

  • A peer query without filters returns 200 with results
  • The same peer query with filters that match nothing returns 404
  • This suggests the endpoint suddenly "doesn't exist" when it clearly does

Detailed design

Specification Changes

Update the following sections in specs/src/routing/http-routing-v1.md:

GET /routing/v1/providers/{cid}

Current:

  • 404 (Not Found): must be returned if no matching records are found.

New:

  • 200 (OK): the response body contains 0 or more records.
  • 404 (Not Found): SHOULD NOT be returned by a server, but if a client receives it, it MUST be interpreted as 200 with 0 results for backward compatibility, resiliency, and maximal interoperability.

GET /routing/v1/peers/{peer-id}

Current:

  • 404 (Not Found): must be returned if no matching records are found.

New:

  • 200 (OK): the response body contains 0 or more peer records.
  • 404 (Not Found): SHOULD NOT be returned by a server, but if a client receives it, it MUST be interpreted as 200 with 0 results for backward compatibility, resiliency, and maximal interoperability.

GET /routing/v1/ipns/{name}

Current:

  • 404 (Not Found): must be returned if no matching records are found.

New:

  • 200 (OK): the response body contains the IPNS Record for the given IPNS Name with Content-Type: application/vnd.ipfs.ipns-record. Any other content type MUST be interpreted as "no record found".
  • 404 (Not Found): SHOULD NOT be returned by a server, but if a client receives it, it MUST be interpreted as "no record found" for backward compatibility, resiliency, and maximal interoperability.

Response Format for Empty Results

For JSON responses (application/json):

{
  "Providers": []
}

or

{
  "Peers": []
}

For NDJSON streaming responses (application/x-ndjson):

  • Return 200 with an empty stream (zero lines)
  • Do not return any data lines

For IPNS responses:

  • Only Content-Type: application/vnd.ipfs.ipns-record indicates a valid IPNS record was found
  • Any other content type (e.g., text/plain with error message) MUST be interpreted as "no record found"
  • This allows servers to return 200 with different content types for error conditions while maintaining backward compatibility

Cache Control

The existing cache control behavior remains unchanged:

  • Empty results should use shorter TTL (typically 15 seconds)
  • Non-empty results can use longer TTL based on the data

Design rationale

Industry Best Practices

Research into REST API design patterns shows that returning 200 with empty collections is a common and recommended practice:

  • Major APIs (GitHub, Google, AWS) follow this pattern for collection endpoints
  • REST principles suggest that a successful query with no results is still a success
  • The collection resource exists even when empty

Semantic Correctness

The HTTP specification defines status codes with specific meanings:

  • 200 OK: The request succeeded, here are the results (which may be empty)
  • 404 Not Found: The requested resource (endpoint) does not exist
  • 204 No Content: Success with explicitly no response body

For collection/search endpoints, the resource is the endpoint itself, not the data it returns. The endpoint exists and functions correctly regardless of whether it finds matching data.

User benefit

  1. Cleaner Browser Console: Web applications will no longer show error messages for normal operations, reducing user confusion and support requests.

  2. Clearer Semantics: Developers can distinguish between "endpoint doesn't exist" (real 404) and "no results found" (200 with empty data).

  3. Consistent Response Structure: Clients can use the same parsing logic whether results are empty or populated.

Compatibility

Backward Compatibility

This change is designed to be fully backward compatible by following the robustness principle - "be conservative in what you send, and liberal in what you accept":

  1. Servers (conservative sending): SHOULD return 200 for empty results
  2. Clients (liberal accepting): MUST handle both:
    • 200 with empty result list (new behavior)
    • 404 (old behavior from legacy servers)

This approach ensures maximum interoperability across the ecosystem while gradually transitioning to the semantically correct behavior.

Migration Strategy

  1. Phase 1: Update server implementations to return 200

    • Can be deployed immediately without breaking existing clients that handle both codes
  2. Phase 2: Update clients to have regression tests that ensure they handle both 200 and 404

    • Clients must maintain 404 handling indefinitely for compatibility with servers that return 404s

Security

This change has no security implications. It only affects the HTTP status code returned for empty results, not the data format, authentication, or authorization mechanisms.

Alternatives

204 No Content

Considered but rejected for the following reasons:

  1. Cannot include response body: 204 explicitly means no response body, but for JSON endpoints we want to maintain consistent response structure (empty arrays/objects)
  2. Incompatible with streaming: NDJSON streams need to specify content type and may include headers even when empty
  3. Inconsistent client handling: Different code paths needed for empty vs non-empty responses
  4. Limited applicability: Could only work for IPNS binary responses, not JSON/NDJSON

Keep 404 Status

Rejected because:

  1. Browser errors: The primary motivation is eliminating confusing console errors
  2. Semantic incorrectness: 404 should mean "endpoint not found" not "no data"
  3. Inconsistent with filters: Same endpoint returning different status codes based on filter parameters is confusing

API Versioning (/routing/v1.1)

Rejected in favor of in-place upgrade because:

  1. Backward compatible: The change can be made without breaking existing clients
  2. Simpler deployment: No need to maintain multiple API versions
  3. Faster adoption: No need for clients to explicitly opt into new version

Test fixtures

Implementations should test the following scenarios:

Empty Results Tests

  1. Providers endpoint with no results:

    GET /routing/v1/providers/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
    Response: 200 OK
    Body: {"Providers": []}
    
  2. NDJSON streaming with no results:

    GET /routing/v1/providers/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
    Accept: application/x-ndjson
    Response: 200 OK
    Content-Type: application/x-ndjson
    Body: [empty - no lines]
    
  3. IPNS endpoint with no results:

    GET /routing/v1/ipns/k51qzi5uqu5dhlbegona8wfyei6jnjuhrulz3t8femxtfmak9134qpqncw3poc
    Accept: application/vnd.ipfs.ipns-record
    Response: 200 OK
    Content-Type: text/plain; charset=utf-8
    Body: delegate error: routing: not found
    

    Note: The Content-Type is NOT application/vnd.ipfs.ipns-record, which indicates no record was found and parsing of body can be skipped. In this example, the body contains text/plain error message for convenience.

Backward Compatibility Tests

Clients MUST correctly handle:

  1. Old server returning 404 → treat as empty results
  2. New server returning 200 with empty body → treat as empty results
  3. New server returning 200 with results → process normally

Copyright

Copyright and related rights waived via CC0.

Discussion (0 threads)

Loading discussions...