<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Quarantine on ErrorZap</title><link>https://errorzap.com/tags/quarantine/</link><description>Recent content in Quarantine on ErrorZap</description><image><title>ErrorZap</title><url>https://errorzap.com/og.png</url><link>https://errorzap.com/og.png</link></image><generator>Hugo</generator><language>en-US</language><copyright>ErrorZap</copyright><lastBuildDate>Tue, 03 Nov 2026 09:00:00 -0700</lastBuildDate><atom:link href="https://errorzap.com/tags/quarantine/index.xml" rel="self" type="application/rss+xml"/><item><title>Bad Rows Go to Quarantine</title><link>https://errorzap.com/posts/bad-rows-go-to-quarantine/</link><pubDate>Tue, 03 Nov 2026 09:00:00 -0700</pubDate><guid>https://errorzap.com/posts/bad-rows-go-to-quarantine/</guid><description>One malformed record should become one visible exception, not a reason to poison or stop an entire daily import.</description><content:encoded><![CDATA[<p>Batch jobs have a talent for turning one weird row into a full-day emergency.</p>
<p>The source sends a date that does not exist. A business name contains a character nobody tested. One detail page returns half an HTML document. A record claims it was updated in the year 2099. The importer reaches that row, throws an exception, and leaves the whole dataset stuck at yesterday.</p>
<p>The usual reaction is to make the parser more forgiving. That can be worse. A parser that accepts everything eventually turns corruption into official data.</p>
<p>The better answer is quarantine.</p>
<h2 id="a-bad-record-is-not-a-bad-run">A bad record is not a bad run</h2>
<p>A robust importer treats records as individual claims.</p>
<p>Each claim passes through structural, semantic, and consistency checks. Good records continue. Suspicious records move to a separate holding area with the reason they were rejected.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>record 4172
</span></span><span style="display:flex;"><span>  identifier: present
</span></span><span style="display:flex;"><span>  date: 2099-31-44       X invalid
</span></span><span style="display:flex;"><span>  required fields: pass
</span></span><span style="display:flex;"><span>  action: quarantine
</span></span><span style="display:flex;"><span>  reason: impossible date
</span></span></code></pre></div><p>The run can finish with 7,999 accepted records and one quarantined record. That is not a hidden partial success. It is an explicit result with a number, a reason, and something a human can inspect.</p>
<h2 id="quarantine-is-not-the-trash">Quarantine is not the trash</h2>
<p>Rejected records must remain recoverable. The point is to prevent them from contaminating the public dataset while preserving enough evidence to repair the rule or correct the source later.</p>
<p>A useful quarantine entry includes:</p>
<ul>
<li>source identifier and source URL when safe;</li>
<li>retrieval time;</li>
<li>validation rule that failed;</li>
<li>bounded copy or hash of the raw input;</li>
<li>parser version;</li>
<li>whether the record existed in the previous dataset;</li>
<li>review status and resolution.</li>
</ul>
<p>Do not dump an entire credential-bearing response into a log. Quarantine should preserve evidence, not create a second security incident.</p>
<h2 id="the-totals-must-add-up">The totals must add up</h2>
<p>The fastest way to lose trust in a pipeline is to make records disappear between counters.</p>
<p>Every run should satisfy a reconciliation equation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>retrieved = accepted + unchanged + quarantined + explicitly skipped
</span></span></code></pre></div><p>If it does not, the run is incomplete.</p>
<p>That equation sounds obvious. It is also where many pipelines fail. They log &ldquo;processed 8,000&rdquo; at the start, &ldquo;saved 7,997&rdquo; at the end, and never explain the missing three.</p>
<p>Thin logs turn those three records into ghosts. A complete ledger turns them into work.</p>
<h2 id="tomorrow-should-not-inherit-todays-wedge">Tomorrow should not inherit today&rsquo;s wedge</h2>
<p>Quarantine also protects future runs.</p>
<p>If one malformed row stays in the upstream source for a week, a crash-on-first-error collector will fail seven days in a row. A quarantine-aware collector will flag the same record, deduplicate the alert, and continue collecting everything else. When the source fixes it, the row can re-enter through the normal validation path.</p>
<p>The operational difference is enormous. One is a brittle daily ceremony. The other is a system that can live in the real world.</p>
<p>Bad rows are inevitable. Silent rows are dangerous. Quarantined rows are manageable.</p>
]]></content:encoded></item></channel></rss>