xbrl duplicate fact values conflict, validation failed
This skill fixes XBRL validation failures from duplicate fact value conflicts. Use it when the same tag shows multiple values or when deduplicating instance facts. It is not for cross-context differences, which are normal; the fix is grouping by context, treating only same-context conflicts as real, and resolving those to the latest amendment.
XBRL duplicate fact values conflict, validation failed
TL;DR
Duplicate XBRL facts with conflicting values are usually not duplicates at all: same tag, different contexts, like quarterly versus annual or different segments. Validation fails when code compares values without comparing contexts. Resolve by keying every fact on tag plus context, and only treat same-tag same-context facts as true duplicates, which usually trace to amended filings mixing old and new instances.
The error
XBRL validation failed: duplicate fact values conflict
tag [us-gaap Revenues] has 3 different values for the same periodWhen this helps
- XBRL validation fails on duplicate fact conflicts
- the same tag shows multiple values for one period
- deduplicating facts from instance documents
- validating a new XBRL pipeline
When it doesn't
- values differ across contexts; that is normal, not duplication
- the instance failed to parse; fix parsing first
- you need segment detail; filter dimensions instead of flagging duplicates
Works with
python 3.9+ with arelle. Context semantics follow XBRL 2.1.
Steps
1. Group the conflicting facts by their contexts
from arelle import Cntlr
cntlr = Cntlr.Cntlr()
model = cntlr.modelManager.modelXbrl
model.load("instance.xml")
seen = {}
for f in model.facts:
if f.qname.localName == "Revenues":
seen.setdefault(f.context.id, []).append(f.value)
for cid, vals in seen.items():
print(cid, vals)Expected: Values grouped by context id. Different contexts explain most conflicts immediately.
2. Check whether the contexts differ by period or segment
from arelle import Cntlr
cntlr = Cntlr.Cntlr()
model = cntlr.modelManager.modelXbrl
model.load("instance.xml")
for cid, ctx in model.contexts.items():
per = ctx.instantDatetime if ctx.isInstantPeriod else (ctx.startDatetime, ctx.endDatetime)
print(cid, per)Expected: The period behind each context. Quarterly versus annual durations are the most common false duplicate.
3. Treat only same-context conflicts as real duplicates
from arelle import Cntlr
cntlr = Cntlr.Cntlr()
model = cntlr.modelManager.modelXbrl
model.load("instance.xml")
real = {}
for f in model.facts:
k = (f.qname.localName, f.context.id)
real.setdefault(k, set()).add(str(f.value))
dupes = {k: v for k, v in real.items() if len(v) != 1}
print("true duplicates:", len(dupes))Expected: A count of genuine same-context conflicts. Zero means the validation error was a context-blind comparison.
4. Resolve true duplicates to the latest amendment
curl -s -A "IntelBriefingBot/1.0" "https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=[cik]&type=10-K&count=10" -o filings.html
grep -c "10-K/A" filings.htmlExpected: The amendment count. True same-context duplicates usually mean instances from an original and an amendment got mixed; keep only the latest accession.
Other ways people phrase this
xbrl duplicate facts same tag different values
Check contexts first. Same tag with different contexts is correct data.
xbrl validation duplicate fact error
Validators flag same-context duplicates. Context-blind code flags everything.
conflicting revenue values xbrl 10-k
Quarterly and annual revenue contexts collide in naive comparisons. Key by context.
Why it happens
XBRL facts are identified by tag plus context, not tag alone. One tag legitimately carries many values across periods, segments, and restatements. Validation that compares values by tag alone manufactures conflicts from correct data. Genuine duplicates, same tag and same context with different values, are rare and usually mean mixed filings.
Edge cases
- Amended filings reissue facts with identical contexts; never load an original and amendment into one model.
- Segment dimensions create contexts that look identical on dates; include dimensions in the key.
- Nil-valued facts versus missing facts are different; handle nil explicitly.
- The companyfacts API dedupes to one value per tag per period, which hides this complexity entirely.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_W-bJxTPEGLLNyrsaJ5tOng
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.