INVALID vs FAILED — Decoding Bundle Status Codes
A bundle comes back rejected. The log says one word. Sometimes that word is INVALID. Sometimes it is FAILED. They both mean the bundle did not land. They both mean the opportunity was not captured. They both mean the effort that went into detecting, evaluating, building, and submitting the transaction resulted in nothing. Zero profit. No on-chain effect. A swing and a miss.
But they are not the same miss. Not even close. They are two fundamentally different kinds of failure, with different causes, different implications, and entirely different paths to resolution. Treating them as interchangeable — lumping them into the same mental bucket of "it didn't work" — is like treating a college application rejection and an expulsion as the same thing because both result in not being enrolled. The outcome is identical. The reason is not.
Understanding the difference between INVALID and FAILED is the difference between debugging efficiently and debugging in circles. One points to the transaction's structure. The other points to the transaction's logic. One says the bundle never entered the competition. The other says the bundle competed and lost. Confusing the two sends you hunting in entirely the wrong part of the codebase, fixing things that are not broken while the actual problem sits untouched.
The Four Outcomes
When a bundle is submitted to the Jito block engine, it enters a pipeline with several stages. The bundle is received, validated, evaluated for tip efficiency, and — if it passes all gates — forwarded to the validator for inclusion in a block. At each stage, the bundle can be accepted and passed forward, or rejected and returned with a status.
There are four possible outcomes.
Landed. The bundle made it through every gate. It entered the tip efficiency competition, its tip-to-compute ratio was competitive enough to be selected, the validator included it in a block, the transactions executed successfully, and the results were committed to the chain. This is the only outcome that counts as success. The bundle is on-chain. The swaps happened. The profit (or at least the attempted operation) materialized.
Invalid. The bundle was rejected before it ever entered the competition. Something about the bundle's structure, format, or basic validity failed a preliminary check. The block engine looked at the bundle, determined it was not eligible to compete, and returned it immediately. The bundle never touched the auction. It was dead on arrival.
Failed. The bundle entered the competition. It passed the structural checks. Its format was valid. It was eligible to participate. The block engine accepted it into the auction pipeline. But when the transactions were executed (or simulated for execution), something went wrong. An instruction errored. A program panicked. An account was in an unexpected state. The execution itself broke. The bundle was structurally sound but operationally broken.
Dropped. The bundle was valid and entered the pipeline, but it was not selected. Its tip efficiency was not competitive enough, or the slot window closed before the bundle could be processed. The bundle was fine — both structurally and operationally — but it lost the competition or ran out of time. It simply did not make the cut.
These four outcomes form a clear hierarchy. Landed is success. Dropped is losing a fair competition. Failed is entering the competition but crashing mid-race. Invalid is being turned away at the registration desk.
INVALID — Rejected at the Door
INVALID is the bluntest form of rejection. The bundle does not make it past the front desk. It is like submitting a loan application where the form is incomplete. The bank does not evaluate your credit history. The bank does not check your income. The bank does not run a risk assessment. The bank looks at the application, sees that the Social Security number field is blank, and sends it back. Application not processed. Not denied — not processed.
An INVALID bundle has a structural or formatting problem that makes it ineligible for the auction. The block engine cannot even consider it because it does not meet the basic prerequisites for consideration.
The causes are varied but share a common theme: something about the bundle itself is wrong, independent of what the transactions are trying to do.
Expired Blockhash
Every Solana transaction includes a recent blockhash that anchors it to a specific window of time. If the blockhash is too old — if too many slots have passed since the block that produced that hash — the transaction is considered expired. A bundle containing an expired transaction is INVALID because it is submitting work that is no longer timely. The block engine rejects it immediately.
This is the equivalent of mailing a rebate form with a deadline that passed last week. The content of the form might be perfect. The receipt might be attached. Every field might be filled in correctly. But the deadline was April 1st and today is April 9th. The processing center does not open the envelope. It sees the postmark date, compares it against the deadline, and returns it. Expired. Not eligible.
In practice, expired blockhashes happen when the bundle submission pipeline has too much latency. The bot reads a blockhash, builds the transaction, signs it, assembles the bundle, and sends it to the block engine. If that process takes too long — if there is a queue, a slow RPC response, a retry loop, or just an inefficient pipeline — the blockhash ages out before the bundle arrives. The fix is straightforward: tighten the pipeline. Reduce latency between blockhash acquisition and bundle submission. Use the freshest possible blockhash at the latest possible moment.
Missing or Insufficient Tip
Jito bundles require a tip — a transfer to a Jito tip account — to participate in the tip efficiency competition. A bundle without a tip instruction, or with a tip that does not meet the minimum floor, is INVALID. It is like showing up to a charity auction without a bidder paddle. You cannot participate in the bidding if you have not registered as a bidder. The bundle needs to include its bid to enter the auction.
Transaction Format Errors
A bundle is a collection of one or more transactions. If any transaction in the bundle is malformed — incorrect number of signatures, invalid account references, oversized, improperly serialized — the entire bundle is INVALID. The block engine performs basic deserialization and validation before doing anything else. If it cannot parse the transactions, it rejects the bundle outright.
This is the equivalent of submitting a job application where the PDF is corrupted. The hiring manager cannot open the file. They do not evaluate your qualifications. They cannot. The file is unreadable. The content might be brilliant, but it never gets seen because the container is broken.
Account Conflicts
If the bundle contains transactions that conflict with each other — trying to write to the same account in incompatible ways, or violating ordering constraints — the bundle can be rejected as INVALID before execution. The block engine detects that the bundle's transactions cannot be executed together coherently and rejects the entire bundle.
The Common Thread
Every INVALID cause shares a characteristic: the problem is detectable without executing the transactions. The block engine does not need to run the programs to know the bundle is broken. It can tell from the structure alone. This is important because it means INVALID errors are diagnosable from the transaction data itself. You do not need to simulate execution. You do not need to understand the program logic. You need to look at the raw transaction bytes, the blockhash, the tip instruction, the account list, and find the structural defect.
INVALID is a packaging problem. The gift inside might be perfect, but the box is taped shut with the label facing inward and the postage missing. Fix the packaging, and the gift reaches its destination.
FAILED — Crashed After Takeoff
FAILED is a different animal entirely. A FAILED bundle passed all the structural checks. The blockhash was fresh. The tip was present and sufficient. The transactions were properly formatted. The account references were valid. The bundle was accepted into the auction pipeline, and the block engine attempted to execute the transactions.
And then something broke.
FAILED is like getting accepted to college, showing up for the first semester, and flunking out. The application was strong enough to earn admission. The SAT scores were fine. The transcripts were fine. The essays were fine. The structural prerequisites were met. But once classes started — once the actual work of being a student began — something went wrong. The student could not handle the coursework, or missed too many classes, or violated the honor code. Admitted but not graduated. Entered but not completed.
A FAILED bundle entered the competition but could not finish the race. The transactions executed (or began executing), and the execution produced an error.
Program Errors
The most common cause of FAILED bundles is a program-level error during execution. The on-chain program ran, encountered a condition it could not handle, and returned an error. InsufficientProfit is one example — the profit check determined the cycle was not profitable enough and reverted the transaction. But there are many others.
A CPI (Cross-Program Invocation) call can fail because the target program rejected the inputs. An account can be in an unexpected state — a pool that was expected to have liquidity might be drained. A numerical overflow can occur when the math produces a value too large for the integer type. A custom error code can be returned for any condition the program author decided to check.
These are logic problems, not format problems. The transaction is well-formed. The instructions are valid. The accounts exist. But the actual execution — the running of the program code with the current on-chain state — produces an error.
Account Lock Conflicts
On Solana, accounts are locked during transaction execution to prevent concurrent writes. If a bundle's transactions need write access to an account that is already locked by another transaction in the same slot, the execution can fail. The bundle is structurally valid — there is nothing wrong with its format — but the runtime environment at the moment of execution prevents it from completing.
This is like arriving at a one-lane bridge from one side while another car is crossing from the other. The road is fine. Your car is fine. Your license is valid. Your destination is correct. But right now, at this specific moment, the resource you need is occupied by someone else. You cannot proceed. Not because anything is wrong with you, but because something else is using what you need.
State Mismatch
The transaction was built against a view of the on-chain state that no longer matches reality. A pool's reserves have changed. A position has been liquidated. An account's balance is different from what the transaction expects. The instructions are correct for the state the bot expected, but wrong for the state that actually exists when the transaction runs.
This is the FedEx package that makes it to the sorting facility and then gets returned because the recipient moved. The address was valid when you shipped it. The label was correct. The postage was paid. The package traveled through the system exactly as designed. But when it arrived at the destination, the destination was no longer what it was supposed to be. The package itself is fine. The world around it changed.
The Common Thread
Every FAILED cause shares a different characteristic from INVALID: the problem is only detectable by executing (or simulating execution of) the transactions. The block engine cannot tell from the structure alone that the bundle will fail. It has to run the code, feed in the current state, and see what happens. FAILED errors require understanding the program logic, the on-chain state, and the interaction between them.
FAILED is a content problem. The packaging is perfect. The box arrives intact. The label is correct. But when you open it, the item inside is broken.
The Debugging Fork
This distinction — INVALID as a structural problem, FAILED as a logical problem — creates a fork in the debugging process. When a bundle comes back rejected, the first question is not "what went wrong?" The first question is "which kind of wrong?"
If the status is INVALID, the debugging path starts with the transaction itself. Is the blockhash fresh? Is the tip instruction present and targeting a valid tip account? Are the transactions properly serialized? Are the signatures valid? Are the account references correct? Is the bundle size within limits? These are all checkable without any knowledge of what the programs do. They are format and structure questions. The answers are in the raw bytes.
If the status is FAILED, the debugging path starts with the execution environment. What error did the program return? What was the on-chain state at execution time? What did the bot expect the state to be? Where does the expected state diverge from the actual state? Is the program's error a known condition (like InsufficientProfit) or an unexpected panic? These require understanding the program logic, the pool mechanics, and the state dynamics. The answers are in the simulation, the logs, and the on-chain data.
Going down the wrong path wastes time and produces false conclusions. If a bundle is INVALID because of an expired blockhash, no amount of program simulation will reveal the problem — the program never ran. If a bundle is FAILED because of an InsufficientProfit revert, no amount of transaction format inspection will help — the format was fine.
It is like debugging a car that will not start. If the engine cranks but does not fire, the problem is in the fuel system, ignition, or compression — you look under the hood. If the key does not turn at all, the problem is in the ignition switch, the steering lock, or the battery — you look at the electrical system. "The car does not start" describes both situations, but the diagnostic path is completely different. A mechanic who hears "won't start" and immediately pulls the spark plugs without first checking whether the engine is cranking is solving the wrong problem half the time.
The Dropped Bundle — A Third Category
Dropped bundles deserve a mention because they are often confused with FAILED, but they are neither INVALID nor FAILED. A Dropped bundle was valid (it passed structural checks) and would have executed successfully (the logic was sound), but it was not selected for inclusion. The tip efficiency was not competitive enough, or the slot window closed.
Dropped is losing a bidding war. You showed up with valid credentials (not INVALID) and a working product (not FAILED), but someone else offered a better deal. The auctioneer picked them instead of you. There is nothing wrong with your bundle. There is nothing to fix in the code. The only lever is the tip — the competitiveness of the bid.
This is like being a qualified job applicant who does not get the position. Your resume is well-formatted (not INVALID). You have the skills to do the job (not FAILED). But someone else had more experience, or asked for less salary, or had an internal referral. You did not get rejected for being unqualified. You got passed over because someone else was more competitive. The fix is not to change your resume format. The fix is not to gain skills you already have. The fix is to become more competitive — better tip efficiency, lower compute usage, faster submission timing.
Why This Taxonomy Matters
Bundle status codes are not just labels. They are diagnostic pointers. Each status code points to a different layer of the system, and knowing which layer to investigate is more than half the battle.
A bot that logs "bundle failed" without distinguishing between INVALID, FAILED, and Dropped is a bot whose operator is flying blind. It is like a hospital that records every patient outcome as either "recovered" or "did not recover." Technically accurate. Diagnostically useless. A patient who died of a heart attack and a patient who left against medical advice both "did not recover," but the hospital's response to each case is entirely different.
The logging system needs to capture and surface the distinction. Every bundle submission should record not just whether it succeeded but which specific status it received on failure. Over time, the distribution of statuses reveals patterns.
A high rate of INVALID bundles points to a systemic pipeline problem. Something in the bundle construction path is consistently producing malformed or expired bundles. The fix is in the infrastructure — the RPC layer, the serialization code, the blockhash management, the tip construction.
A high rate of FAILED bundles points to a prediction problem. The bot is consistently building transactions that are structurally correct but logically wrong — targeting stale state, miscalculating outputs, hitting program errors. The fix is in the strategy layer — the screener's accuracy, the state freshness, the math precision.
A high rate of Dropped bundles points to a competitiveness problem. The bot is building valid, executable bundles that just are not winning the tip efficiency competition. The fix is in the economics — better tip calibration, lower compute overhead, faster timing.
Three different failure modes. Three different layers of the system. Three different fix strategies. Lumping them together means never knowing which layer to improve.
The Emotional Trap
There is a psychological dimension to this distinction that is easy to overlook. INVALID bundles feel worse than they are. FAILED bundles feel better than they are. The emotional response to each is inverted from its actual severity.
An INVALID bundle feels like a fundamental failure. The bundle was so broken it did not even enter the competition. It feels like showing up to the SAT and being told you filled out the answer sheet wrong — not that you got the answers wrong, but that your sheet cannot even be scored. It feels deeply incompetent.
But INVALID errors are usually the easiest to fix. They are structural. They are deterministic. An expired blockhash produces the same INVALID result every time, and fixing the latency that caused the expiration is a straightforward engineering task. INVALID errors are like typos in an essay — embarrassing to find, but trivial to correct.
FAILED bundles, by contrast, feel less alarming. The bundle entered the auction. It was considered. It almost worked. It feels like placing second in a race — close, but not quite. The emotional response is "I was almost there." The temptation is to think the fix is a small tweak, a minor adjustment, an incremental improvement.
But FAILED errors can be deeply complex. A CPI error might stem from a misunderstanding of the target program's account requirements. A state mismatch might reflect a fundamental flaw in the screener's state management. An InsufficientProfit revert might indicate that the prediction model is systematically overestimating returns. These are not typos. These are structural problems in the logic layer that can take days or weeks to diagnose and resolve.
The INVALID bundle that feels devastating is a five-minute fix. The FAILED bundle that feels encouraging is a two-week investigation. Do not let the emotional valence guide the debugging priority. Let the diagnostic data guide it.
Reading the Status Like a Doctor
A good doctor does not just record "patient is sick." A good doctor records the specific symptoms, the vital signs, the lab results, and the imaging findings. Each data point narrows the differential diagnosis. Each piece of information eliminates possibilities and points toward the actual condition.
Bundle status codes are vital signs. They are the first, coarsest layer of diagnosis. INVALID narrows the search to the structural layer. FAILED narrows it to the execution layer. Dropped narrows it to the economic layer. Each status eliminates two-thirds of the possible problem space before the detailed investigation even begins.
But the status code alone is not sufficient. Within FAILED, there are dozens of possible program errors, each pointing to a different root cause. Within INVALID, there are several possible structural defects, each requiring a different fix. The status code is the triage — which department of the hospital does this patient go to? The detailed error message, the simulation output, the transaction logs — those are the actual diagnosis.
The system needs both layers. The coarse triage (status code) and the detailed diagnosis (error data). Without the triage, every failure triggers a full investigation across all possible causes. Without the detailed diagnosis, the triage narrows the field but does not identify the specific problem. Together, they form a diagnostic funnel that efficiently converts "something went wrong" into "this specific thing went wrong for this specific reason."
Building the Classification Reflex
After enough bundles, the classification becomes reflexive. The status code arrives and the mental model activates instantly. INVALID — check the pipeline. FAILED — check the logic. Dropped — check the economics. The debugging session starts in the right place, on the right layer, looking at the right data.
This reflex saves hours. It is the difference between a doctor who reads a chest X-ray and immediately knows whether the problem is cardiac, pulmonary, or musculoskeletal, versus a doctor who orders every test for every organ system and waits for something to come back abnormal. Both eventually reach the diagnosis. One gets there in minutes. The other gets there in days.
The same word — "failure" — describes bundles that did not enter the auction, bundles that entered and crashed, and bundles that entered and lost. Three entirely different situations. Three entirely different causes. Three entirely different solutions. The status code is the fork in the road that determines which direction the investigation goes. Reading it correctly is the first skill. Acting on it correctly is the second.
The bundle comes back rejected. The log shows a status. And now, instead of a vague sense that "it didn't work," there is a precise pointer to where the problem lives. Not in the code generally. Not in the system broadly. In a specific layer, at a specific stage, for a specific reason.
That precision is everything. The rest is just following the pointer.
Disclaimer
This article is for informational and educational purposes only and does not constitute financial, investment, legal, or professional advice. Content is produced independently and supported by advertising revenue. While we strive for accuracy, this article may contain unintentional errors or outdated information. Readers should independently verify all facts and data before making decisions. Company names and trademarks are referenced for analysis purposes under fair use principles. Always consult qualified professionals before making financial or legal decisions.