GET /toml
Returns TOML documents with TOML 1.0 spec violations and parser ambiguity. Default mixes int, string, and float in a single array. Use ?mode= to isolate other violations: unquoted datetime, duplicate tables, illegal nesting, impossible offsets, dotted-key/table collisions, or trailing commas in inline tables.
mode
mixed-array-types (default; array mixes int, string, and float; TOML 1.0 forbids mixed types in arrays; many parsers accept silently and downstream schema validators fail), unquoted-datetime (datetime value is unquoted and not in RFC 3339 format), duplicate-table (the same table is defined twice), invalid-nesting (a table is defined after it has been used as a simple key), datetime-offset-lie (offset +99:00 is structurally valid TOML datetime syntax but semantically impossible; strict parsers with timezone validation reject, others re-emit the garbage offset), dotted-key-table-collision (table [server] is defined first, then server.host is re-defined as a dotted key; TOML 1.0 forbids re-defining a table via dotted keys), trailing-comma-inline-table (inline table has a trailing comma after the last key-value pair; TOML 1.0 forbids this unlike arrays; many parsers accept it silently).
control Compare against the well-formed counterpart: not.catastrophic.io/toml side-by-side
build a request:
expect: An application/toml response with one TOML 1.0 violation. Many violations are accepted silently by lenient parsers, causing schema drift downstream. The `note` is in the X-Chaos-Toml-Note response header.
curl -si 'https://chaos.catastrophic.io/toml?mode=mixed-array-types'
# Python 3.11+ ships tomllib in the stdlib.
import urllib.request, tomllib
resp = urllib.request.urlopen("https://chaos.catastrophic.io/toml?mode=mixed-array-types")
print("Content-Type:", resp.headers.get("Content-Type"))
print("X-Chaos-Toml-Mode:", resp.headers.get("X-Chaos-Toml-Mode"))
print("X-Chaos-Toml-Note:", resp.headers.get("X-Chaos-Toml-Note"))
raw = resp.read()
try:
parsed = tomllib.loads(raw.decode())
print("parsed OK, top-level keys:", list(parsed.keys()))
except tomllib.TOMLDecodeError as e:
print("tomllib rejected:", e)
// npm: @iarna/toml or smol-toml. Example uses smol-toml.
import { parse } from "smol-toml";
const res = await fetch("https://chaos.catastrophic.io/toml?mode=mixed-array-types");
console.log("Content-Type:", res.headers.get("content-type"));
console.log("X-Chaos-Toml-Mode:", res.headers.get("x-chaos-toml-mode"));
console.log("X-Chaos-Toml-Note:", res.headers.get("x-chaos-toml-note"));
const text = await res.text();
try {
console.log("parsed:", parse(text));
} catch (e) {
console.log("parser rejected:", e.message);
}
package main
// go get github.com/BurntSushi/toml
import (
"fmt"
"io"
"net/http"
"github.com/BurntSushi/toml"
)
func main() {
resp, _ := http.Get("https://chaos.catastrophic.io/toml?mode=mixed-array-types")
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
fmt.Println("X-Chaos-Toml-Mode:", resp.Header.Get("X-Chaos-Toml-Mode"))
var out map[string]any
if _, err := toml.Decode(string(raw), &out); err != nil {
fmt.Println("decoder rejected:", err)
} else {
fmt.Println("decoded keys:", out)
}
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
// toml = "0.8"
fn main() -> Result<(), Box> {
let resp = reqwest::blocking::get("https://chaos.catastrophic.io/toml?mode=mixed-array-types")?;
println!("Content-Type: {:?}", resp.headers().get("content-type"));
println!("X-Chaos-Toml-Mode: {:?}", resp.headers().get("x-chaos-toml-mode"));
let text = resp.text()?;
match toml::from_str::(&text) {
Ok(v) => println!("parsed: {:?}", v),
Err(e) => println!("parser rejected: {}", e),
}
Ok(())
}
// Add to build.gradle: implementation("org.tomlj:tomlj:1.1.1")
import java.net.URI;
import java.net.http.*;
import org.tomlj.Toml;
import org.tomlj.TomlParseResult;
public class TomlChaos {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://chaos.catastrophic.io/toml?mode=mixed-array-types")).build();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("Content-Type: " +
resp.headers().firstValue("Content-Type").orElse(""));
System.out.println("X-Chaos-Toml-Mode: " +
resp.headers().firstValue("X-Chaos-Toml-Mode").orElse(""));
TomlParseResult r = Toml.parse(resp.body());
if (r.hasErrors()) r.errors().forEach(e -> System.out.println("parse error: " + e));
else System.out.println("keys: " + r.keySet());
}
}
// NuGet: Tomlyn
using Tomlyn;
using var client = new HttpClient();
var resp = await client.GetAsync("https://chaos.catastrophic.io/toml?mode=mixed-array-types");
Console.WriteLine($"Content-Type: {resp.Content.Headers.ContentType}");
Console.WriteLine($"X-Chaos-Toml-Mode: " +
$"{resp.Headers.GetValues("X-Chaos-Toml-Mode").FirstOrDefault()}");
var text = await resp.Content.ReadAsStringAsync();
var (doc, diags) = (Toml.Parse(text), Toml.Parse(text).Diagnostics);
Console.WriteLine($"diagnostics: {diags.Count}");
foreach (var d in diags) Console.WriteLine($" {d}");
# gem install toml-rb
require "net/http"
require "toml-rb"
uri = URI("https://chaos.catastrophic.io/toml?mode=mixed-array-types")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
res = http.get(uri.request_uri)
puts "Content-Type: #{res['Content-Type']}"
puts "X-Chaos-Toml-Mode: #{res['X-Chaos-Toml-Mode']}"
puts "X-Chaos-Toml-Note: #{res['X-Chaos-Toml-Note']}"
begin
parsed = TomlRB.parse(res.body)
puts "parsed keys: #{parsed.keys.inspect}"
rescue => e
puts "parser rejected: #{e.message}"
end
end
# PSToml (Install-Module PSToml) or just dump raw.
$r = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/toml?mode=mixed-array-types'
"Content-Type: $($r.Headers['Content-Type'])"
"X-Chaos-Toml-Mode: $($r.Headers['X-Chaos-Toml-Mode'])"
"X-Chaos-Toml-Note: $($r.Headers['X-Chaos-Toml-Note'])"
$r.Content
headers
body