InterviewKata
AI engineering · Case study 04 · AI in the real world

Mata v. Avianca: fluent isn't verified

In March 2023, lawyers suing the airline Avianca filed a brief citing court decisions that didn't exist. ChatGPT had written them, complete with case names, judges, quotes and citations. When the lawyer asked it whether one was real, it said the case "does indeed exist" and could be found on Westlaw and LexisNexis. A federal judge sanctioned the lawyers, and the case became the standard warning about treating fluent AI output as fact.

A 2-minute conversation: Sam asks, Priya explains
0:00 / 2:14

1. The situation

The plaintiff, Roberto Mata, was suing Avianca, and the airline asked the court to dismiss the claim. The plaintiff's firm usually worked in New York state courts and used a research service with limited access to federal cases. Researching the federal question, one of its lawyers turned to ChatGPT, which he "falsely assumed was like a super search engine".

Real caseFrom the court's own Opinion and Order on Sanctions (Mata v. Avianca, Inc., No. 22-cv-1461, Southern District of New York, 22 June 2023, Judge P. Kevin Castel). Every citation in the demos below comes from that opinion.

2. What happened, and what the court decided

DateWhat the opinion records
1 March 2023A brief opposing dismissal cites decisions including "Varghese v. China Southern Airlines" and "Miller v. United Airlines".
Next weeksNeither the airline's lawyers nor the court can find them.
25 April 2023The firm files copies of the "opinions". One, Varghese, has analysis the judge calls "gibberish"; its docket number belongs to another case, and its citation to J.D. v. Azar.
Asked directlyAsked whether Varghese was real, ChatGPT said it "does indeed exist" and was available on Westlaw and LexisNexis.
25 May 2023After an order to show cause, the lawyers acknowledge that six decisions (Varghese, Shaboon, Petersen, Martinez, Durden and Miller) were generated by ChatGPT and do not exist.
22 June 2023Sanctions: a $5,000 penalty, and letters to the client and to each judge falsely named as the author of a fake opinion. The court found subjective bad faith, because the lawyers stood by the fake cases after their existence was questioned.

The judge was clear that the tool wasn't the problem: "there is nothing inherently improper about using a reliable artificial intelligence tool for assistance. But existing rules impose a gatekeeping role on attorneys to ensure the accuracy of their filings."

3. How fluent text becomes a false citation

Why a language model produces a convincing citation that doesn't exist, and where a check would have caught it.

4. The control in code

A citation checker. It reads each citation, looks it up in a trusted index (in practice a legal database's API), and reports one of three results: verified, not found, or a mismatch where the name and the citation belong to different cases. That last one matters: one of the brief's citations used the real name Zicherman v. Korean Air Lines, whose real citation is 516 U.S. 217, with a citation that belongs to Miccosukee Tribe v. United States. The program was run in all three languages; each prints the output below it.

import re

# A tiny trusted index: citation -> case name. In practice, a legal database's API.
# These five pairs are real, and each one appears in the Mata v. Avianca sanctions opinion.
INDEX = {
    "516 U.S. 217": "Zicherman v. Korean Air Lines Co.",
    "525 U.S. 155": "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng",
    "925 F.3d 1291": "J.D. v. Azar",
    "516 F.3d 1235": "Miccosukee Tribe v. United States",
    "174 F.3d 352": "Greenleaf v. Garlock, Inc.",
}
CITE = re.compile(r"^(?P<name>.+?), (?P<cite>\d+ (?:U\.S\.|F\.\dd) \d+)")


def surname(name):
    return name.split(" v. ")[0].split()[-1].strip(",").lower()


def check(citation):
    m = CITE.match(citation)
    if not m:
        return "unreadable", "not in a recognised citation format"
    name, cite = m["name"], m["cite"]
    if cite in INDEX:
        if surname(INDEX[cite]) == surname(name):
            return "verified", INDEX[cite]
        return "mismatch", f"{cite} is {INDEX[cite]}"
    elsewhere = [c for c, n in INDEX.items() if surname(n) == surname(name)]
    if elsewhere:
        return "mismatch", f"a case of that name is at {elsewhere[0]}, not {cite}"
    return "not found", "no case at that citation in the index"


BRIEF = [  # four citations as they appeared in the brief, per the opinion
    "Varghese v. China Southern Airlines Co., Ltd., 925 F.3d 1339 (11th Cir. 2019)",
    "Zicherman v. Korean Air Lines Co., Ltd., 516 F.3d 1237 (11th Cir. 2008)",
    "Miller v. United Airlines, Inc., 174 F.3d 366 (2d Cir. 1999)",
    "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng, 525 U.S. 155 (1999)",
]
results = [check(c) for c in BRIEF]
for c, (status, why) in zip(BRIEF, results):
    print(f"{status:<10} {c.split(',')[0]}: {why}")
ok = sum(s == "verified" for s, _ in results)
print(f"{ok} of {len(BRIEF)} verified; do not file until every citation is verified and read")
// A tiny trusted index: citation -> case name. In practice, a legal database's API.
// These five pairs are real, and each one appears in the Mata v. Avianca sanctions opinion.
const INDEX: Record<string, string> = {
  "516 U.S. 217": "Zicherman v. Korean Air Lines Co.",
  "525 U.S. 155": "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng",
  "925 F.3d 1291": "J.D. v. Azar",
  "516 F.3d 1235": "Miccosukee Tribe v. United States",
  "174 F.3d 352": "Greenleaf v. Garlock, Inc.",
};
const CITE = /^(?<name>.+?), (?<cite>\d+ (?:U\.S\.|F\.\dd) \d+)/;

const surname = (name: string) => name.split(" v. ")[0].split(" ").pop()!.replace(/,$/, "").toLowerCase();

function check(citation: string): [string, string] {
  const m = CITE.exec(citation);
  if (!m?.groups) return ["unreadable", "not in a recognised citation format"];
  const { name, cite } = m.groups;
  if (cite in INDEX) {
    if (surname(INDEX[cite]) === surname(name)) return ["verified", INDEX[cite]];
    return ["mismatch", `${cite} is ${INDEX[cite]}`];
  }
  const elsewhere = Object.keys(INDEX).filter((c) => surname(INDEX[c]) === surname(name));
  if (elsewhere.length) return ["mismatch", `a case of that name is at ${elsewhere[0]}, not ${cite}`];
  return ["not found", "no case at that citation in the index"];
}

const BRIEF = [  // four citations as they appeared in the brief, per the opinion
  "Varghese v. China Southern Airlines Co., Ltd., 925 F.3d 1339 (11th Cir. 2019)",
  "Zicherman v. Korean Air Lines Co., Ltd., 516 F.3d 1237 (11th Cir. 2008)",
  "Miller v. United Airlines, Inc., 174 F.3d 366 (2d Cir. 1999)",
  "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng, 525 U.S. 155 (1999)",
];
const results = BRIEF.map(check);
BRIEF.forEach((c, i) => console.log(`${results[i][0].padEnd(10)} ${c.split(",")[0]}: ${results[i][1]}`));
const ok = results.filter(([s]) => s === "verified").length;
console.log(`${ok} of ${BRIEF.length} verified; do not file until every citation is verified and read`);
import java.util.*;
import java.util.regex.*;

public class Main {
    // A tiny trusted index: citation -> case name. In practice, a legal database's API.
    // These five pairs are real, and each one appears in the Mata v. Avianca sanctions opinion.
    static final Map<String, String> INDEX = new LinkedHashMap<>();
    static {
        INDEX.put("516 U.S. 217", "Zicherman v. Korean Air Lines Co.");
        INDEX.put("525 U.S. 155", "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng");
        INDEX.put("925 F.3d 1291", "J.D. v. Azar");
        INDEX.put("516 F.3d 1235", "Miccosukee Tribe v. United States");
        INDEX.put("174 F.3d 352", "Greenleaf v. Garlock, Inc.");
    }
    static final Pattern CITE = Pattern.compile("^(?<name>.+?), (?<cite>\\d+ (?:U\\.S\\.|F\\.\\dd) \\d+)");

    static String surname(String name) {
        String[] parts = name.split(" v\\. ")[0].split(" ");
        return parts[parts.length - 1].replaceAll(",$", "").toLowerCase();
    }

    static String[] check(String citation) {
        Matcher m = CITE.matcher(citation);
        if (!m.find()) return new String[]{"unreadable", "not in a recognised citation format"};
        String name = m.group("name"), cite = m.group("cite");
        if (INDEX.containsKey(cite)) {
            if (surname(INDEX.get(cite)).equals(surname(name))) return new String[]{"verified", INDEX.get(cite)};
            return new String[]{"mismatch", cite + " is " + INDEX.get(cite)};
        }
        for (Map.Entry<String, String> e : INDEX.entrySet())
            if (surname(e.getValue()).equals(surname(name))) return new String[]{"mismatch", "a case of that name is at " + e.getKey() + ", not " + cite};
        return new String[]{"not found", "no case at that citation in the index"};
    }

    public static void main(String[] args) {
        List<String> brief = List.of(  // four citations as they appeared in the brief, per the opinion
            "Varghese v. China Southern Airlines Co., Ltd., 925 F.3d 1339 (11th Cir. 2019)",
            "Zicherman v. Korean Air Lines Co., Ltd., 516 F.3d 1237 (11th Cir. 2008)",
            "Miller v. United Airlines, Inc., 174 F.3d 366 (2d Cir. 1999)",
            "El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng, 525 U.S. 155 (1999)");
        int ok = 0;
        for (String c : brief) {
            String[] r = check(c);
            if (r[0].equals("verified")) ok++;
            System.out.println(String.format("%-10s %s: %s", r[0], c.split(",")[0], r[1]));
        }
        System.out.println(ok + " of " + brief.size() + " verified; do not file until every citation is verified and read");
    }
}
not found  Varghese v. China Southern Airlines Co.: no case at that citation in the index
mismatch   Zicherman v. Korean Air Lines Co.: a case of that name is at 516 U.S. 217, not 516 F.3d 1237
not found  Miller v. United Airlines: no case at that citation in the index
verified   El Al Israel Airlines: El Al Israel Airlines, Ltd. v. Tsui Yuan Tseng
1 of 4 verified; do not file until every citation is verified and read

Verifying that a case exists is the minimum. A real case can still be quoted wrongly or cited for something it doesn't say, which is why the last step is a person reading it.

5. Try it: check a list of citations

Edit the list, one citation per line, and see what the checker says. The index holds only the five real cases named in the opinion, so anything else is "not found": exactly what you want from a checker when it can't confirm something.

6. What happened next

The sanctions were modest in money and large in reputation. The opinion attached the fake decisions and the ChatGPT screenshots for anyone to read, and required letters to every judge falsely named as an author. Since then, courts have dealt with many more filings that cite AI-invented cases, and some judges have issued orders requiring lawyers to certify that anything an AI tool produced was checked.

7. Lessons

8. Your turn

  1. Find your citations (10 min). Where does AI output in your work cite something: a paper, an API, a ticket, a law, a figure?
  2. Name the source of truth (10 min). For each, what independent source would confirm it?
  3. Design the check (10 min). What does "verified" mean, and what happens when something can't be verified?
Say it in the interview
  • "How do you stop an AI system citing things that don't exist?" Retrieve from a real source first, generate from what's retrieved, then verify every reference against an independent index before anything ships, with a person reading the important ones. In Mata v. Avianca, ChatGPT invented six court decisions and confirmed they were real when asked.

9. Check yourself

Asked whether Varghese was real, what did ChatGPT say?

Asking the model to check itself isn't verification.

What did the judge say about using AI tools?

The duty to check stays with the person who files.

Why flag a mismatch, not just a missing case?

The brief cited the real Zicherman case at the wrong citation.

10. Sources and further reading

ResourceWhy
Mata v. Avianca: Opinion and Order on Sanctions (S.D.N.Y., 22 June 2023)Every fact, quote and citation on this page, with the fake opinions and screenshots attached.
Modules 03, 15 and 17Why models invent, how retrieval grounds them, and how to test it.