Blog
Articles
Why AI coding agents break data pipelines, and how to catch it before merge

Why AI coding agents break data pipelines, and how to catch it before merge

Articles
November 4, 2026
Team Foundational
Subscribe to our Newsletter
Get the latest from our team delivered to your inbox
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Ready to get started?
Try It Free
Illustration of a code change flowing from a coding agent into a pipeline of connected systems, with one broken link and a warning downstream.

When a coding agent breaks a pipeline, the diff usually looks fine. The tests pass, the build is green, and a reviewer approves it. Then a job fails overnight, or worse, keeps running and writes wrong numbers. The AI coding agent didn't write bad code. It changed something other systems read, and it couldn't see them. We walked through one such change in The change passed every test.

That's true for application teams as much as data teams. A Java service, a TypeScript API and a Python job can all write tables that someone else's pipeline reads. The agent sees its own repository. The pipeline lives somewhere else.

Four ways it happens

1. A rename the consumer never hears about. The agent renames a column to match a new field name. Every reference inside the repo gets updated. A Spark job in another repository still selects the old name and fails, or a dashboard silently shows blanks.

2. A value change that doesn't error. The agent swaps single-letter status codes for readable words. Nothing breaks at the type level. A downstream filter on the old code now matches nothing, so a report drops to zero and nobody gets an alert.

3. A table name the code never spells out. The consumer reads whichever table its deployment config points to, or builds the name at run time, as JCL does with dataset names. A search across the code finds no match, so the agent concludes nothing depends on it.

4. The same data under different names. A COBOL program reads a Db2 column into its own variable from a copybook. A Python job reads the same column through an ORM. Nothing ties those names together except the table, so neither search nor a language server connects them.

Why better prompts and models don't fix it

Each failure is missing information, not weak reasoning. A stronger model searches harder and finds more candidates, but it still can't confirm which ones really read the table. A rules file can tell the agent to check for consumers, but it can't list them, because that list lives in other teams' code and keeps changing.

Fix 1: give the agent the impact before it edits

Foundational Context of Code and Data analyzes source code across your repositories and languages and connects each table, column and dataset to what reads and writes it, with owners. The agent queries it over MCP in the middle of a task: "What reads or writes this column, across all our repos?" With the answer, it can propose a safer change, such as adding a column instead of changing values in place, or flagging the owners in the pull request. How to set it up in your coding agent.

Fix 2: check again at review

Agents don't always call the tool they should. AI code review with impact analysis on the pull request shows the reviewer the downstream jobs, services, dashboards and other consumers a change affects, whether a person or an agent wrote it. That's the point where the pipeline owner sees the change before it merges. See impact analysis.

A checklist for teams letting agents touch shared tables

  • Add a rule: before renaming, dropping or changing the type or values of a table, column or dataset, list what depends on it.
  • Give the agent a tool that can answer that across repos and languages.
  • Turn on impact analysis for the repos where agents open pull requests.
  • Treat value changes like schema changes. They break consumers just as often and fail more quietly.
  • Review a few agent pull requests a month to see what the checks caught.

FAQ

Do these failures only happen with AI-written code?

No. People make the same changes. Agents just make more of them, faster, and with less context about other teams' systems.

Will tests catch it?

Usually not. Tests run inside the repository that changed. The consumer that breaks lives in another one.

Is this only a data engineering problem?

No. Any service that writes a shared table, topic or file can break a pipeline downstream.

code snippet <goes here>
<style>.horizontal-trigger {height: calc(100% - 100vh);}</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/ScrollTrigger.min.js"></script>
<script>
// © Code by T.RICKS, https://www.timothyricks.com/
// Copyright 2021, T.RICKS, All rights reserved.
// You have the license to use this code in your projects but not to redistribute it to others
gsap.registerPlugin(ScrollTrigger);
let horizontalItem = $(".horizontal-item");
let horizontalSection = $(".horizontal-section");
let moveDistance;
function calculateScroll() {
 // Desktop
 let itemsInView = 3;
 let scrollSpeed = 1.2;  if (window.matchMedia("(max-width: 479px)").matches) {
   // Mobile Portrait
   itemsInView = 1;
   scrollSpeed = 1.2;
 } else if (window.matchMedia("(max-width: 767px)").matches) {
   // Mobile Landscape
   itemsInView = 1;
   scrollSpeed = 1.2;
 } else if (window.matchMedia("(max-width: 991px)").matches) {
   // Tablet
   itemsInView = 2;
   scrollSpeed = 1.2;
 }
 let moveAmount = horizontalItem.length - itemsInView;
 let minHeight =
   scrollSpeed * horizontalItem.outerWidth() * horizontalItem.length;
 if (moveAmount <= 0) {
   moveAmount = 0;
   minHeight = 0;
   // horizontalSection.css('height', '100vh');
 } else {
   horizontalSection.css("height", "200vh");
 }
 moveDistance = horizontalItem.outerWidth() * moveAmount;
 horizontalSection.css("min-height", minHeight + "px");
}
calculateScroll();
window.onresize = function () {
 calculateScroll();
};let tl = gsap.timeline({
 scrollTrigger: {
   trigger: ".horizontal-trigger",
   // trigger element - viewport
   start: "top top",
   end: "bottom top",
   invalidateOnRefresh: true,
   scrub: 1
 }
});
tl.to(".horizontal-section .list", {
 x: () => -moveDistance,
 duration: 1
});
</script>

Want to see the impact of a change on your own code?

Book a demo and we'll walk through it with your stack.

Want to see the impact of a change on your own code?

Book a demo and we'll walk through it with your stack.

Want to see the impact of a change on your own code?

Book a demo and we'll walk through it with your stack.

Share this post
Subscribe to our Newsletter
Get the latest from our team delivered to your inbox
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Ready to get started?
Try It Free

Governance that starts at the source.