online / endpoints 59 / categories 14 / rate 60/min/ip /

GET /retry-mismatch

GET /retry-mismatch

Token-keyed retry chaos. The first call for a given id returns version 1; any subsequent call for the same id within a 60-second window returns version 2 — same response shape, different data. Tests whether retry logic silently picks up changed data without noticing.

id Client-supplied identity token (1–128 chars). State is tracked per id. Use any string you like — uuids, request IDs, anything stable across the retry.
build a request:

expect: 200 OK with JSON. First call for a given id returns data.version=1; same id within 60s returns data.version=2. X-Chaos-Retry-Replayed flips on the second call.

bash
# First call — version 1
curl -s 'https://chaos.catastrophic.io/retry-mismatch?id=test-1' | python -m json.tool

# Second call within 60s — same id, different response
curl -s 'https://chaos.catastrophic.io/retry-mismatch?id=test-1' | python -m json.tool
import json, urllib.request
url = "https://chaos.catastrophic.io/retry-mismatch?id=test-1"
r1 = json.loads(urllib.request.urlopen(url).read())
r2 = json.loads(urllib.request.urlopen(url).read())
print(r1["data"]["version"], r2["data"]["version"])   # 1, 2
const url = "https://chaos.catastrophic.io/retry-mismatch?id=test-1";
const r1  = await (await fetch(url)).json();
const r2  = await (await fetch(url)).json();
console.log(r1.data.version, r2.data.version);        // 1, 2
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type response struct {
    Data struct {
        Version int `json:"version"`
    } `json:"data"`
}

func fetch(url string) response {
    resp, _ := http.Get(url)
    defer resp.Body.Close()
    var r response
    json.NewDecoder(resp.Body).Decode(&r)
    return r
}

func main() {
    url := "https://chaos.catastrophic.io/retry-mismatch?id=test-1"
    fmt.Println(fetch(url).Data.Version, fetch(url).Data.Version)   // 1 2
}
// Cargo.toml: reqwest    = { version = "0.12", features = ["blocking", "json"] }
//             serde_json = "1"
fn main() -> Result<(), Box> {
    let url = "https://chaos.catastrophic.io/retry-mismatch?id=test-1";
    let client = reqwest::blocking::Client::new();
    let r1: serde_json::Value = client.get(url).send()?.json()?;
    let r2: serde_json::Value = client.get(url).send()?.json()?;
    println!("{} {}", r1["data"]["version"], r2["data"]["version"]);   // 1 2
    Ok(())
}
// Requires Jackson
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.*;

public class RetryMismatch {
    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var url = URI.create("https://chaos.catastrophic.io/retry-mismatch?id=test-1");
        var mapper = new ObjectMapper();
        var r1 = mapper.readTree(client.send(
            HttpRequest.newBuilder(url).build(), HttpResponse.BodyHandlers.ofString()).body());
        var r2 = mapper.readTree(client.send(
            HttpRequest.newBuilder(url).build(), HttpResponse.BodyHandlers.ofString()).body());
        System.out.println(r1.at("/data/version") + " " + r2.at("/data/version"));   // 1 2
    }
}
using System.Text.Json;
using var client = new HttpClient();
var url = "https://chaos.catastrophic.io/retry-mismatch?id=test-1";

async Task Version() {
    var raw = await client.GetStringAsync(url);
    return JsonDocument.Parse(raw).RootElement.GetProperty("data").GetProperty("version").GetInt32();
}
Console.WriteLine($"{await Version()} {await Version()}");   // 1 2
require "net/http"
require "json"
uri = URI("https://chaos.catastrophic.io/retry-mismatch?id=test-1")
fetch = -> { JSON.parse(Net::HTTP.get(uri)).dig("data", "version") }
puts "#{fetch.call} #{fetch.call}"   # 1 2
$first  = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/retry-mismatch?id=test-1'
$second = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/retry-mismatch?id=test-1'
($first.Content  | ConvertFrom-Json).data.version    # 1
($second.Content | ConvertFrom-Json).data.version    # 2
$first.Headers['X-Chaos-Retry-Replayed']             # false
$second.Headers['X-Chaos-Retry-Replayed']            # true