When IRIS rejects a filing, the code is doing more than flagging a failure — it tells you exactly where in the pipeline the problem happened, and that location is what determines the fix. The IRS Information Returns Intake System can report errors at three distinct stages. The first is authentication, where the shared OAuth gateway returns an ESRV code such as ESRV306 for a bad JWT, long before IRIS reads your XML. The second is intake, where a malformed transmission earns an HTTP 400 and no Receipt ID is ever issued. The third is processing, where IRIS validates your data asynchronously and returns business-rule codes like TMFST002 or S1H022 inside your acknowledgement. Knowing which layer fired is the single most useful diagnostic step you can take, because each one points at a completely different fix.
In this story
Read the Layer Before You Read the Code
If you remember only one thing from this guide, make it this: work out which layer produced the error before you try to decode the error itself. A 401 carrying an ESRV body is an authentication problem. A 400 with no Receipt ID is an intake problem. A rule ID like SHAREDIRFORM014 buried inside an <ErrorInformationGrp> is a data problem. Each layer has a different owner and a different fix, and chasing the wrong one is the biggest time sink in IRIS troubleshooting.
Those three layers fire in a strict order, and the order itself is diagnostic. Authentication errors come from the shared e-Services OAuth gateway that fronts IRIS, TIN Matching, and the Secure Object Repository, and they happen before the system has looked at your return at all. Intake errors happen a moment later, when IRIS reads your transmission manifest but refuses the file before it ever assigns a Receipt ID. Processing errors arrive last, inside the asynchronous acknowledgement you poll for, after the return has been accepted into the queue for full validation. Reading the HTTP status and the body shape first tells you which of the three you are actually dealing with.
A few terms recur throughout, so it helps to pin them down once. A2A is the machine-to-machine API channel, as opposed to the web portal. A TCC is your IRS-assigned Transmitter Control Code, the identifier that ties a transmission back to your approved IR Application. And a Receipt ID is the tracking number IRIS returns the instant it accepts and saves a transmission — which is precisely why a rejection that arrives without one means the file was never stored and there is nothing to replace.
| Layer | Code shape | Where it fires | What you fix |
|---|---|---|---|
| Authentication | ESRV### | OAuth gateway, before IRIS sees your XML | Certificate, JWT, or scope |
| Intake | HTTP 400 | Manifest check, before a Receipt ID | Manifest, test code, or schema |
| Processing | Rule IDs | Asynchronous acknowledgement | The flagged XML element |
The pre-Receipt intake errors live in Pub 5718 Table 6-1, the IRIS A2A specification. The per-rule reject and report codes come from the IRIS Business Rules TY2025 v1.4 catalog. The ESRV authentication codes are documented in the e-Services API Authorization User Guide §4. For the authoritative A2A error model, see IRS Publication 5718.
Layer 1 — ESRV Errors Are About Credentials, Not Your Return
ESRV codes are returned by the shared e-Services OAuth gateway that sits in front of IRIS, and they fire before the system has validated a single byte of your XML. That timing is the whole point: when you see an ESRV code, the fix is always somewhere in your credentials, your certificate, or your token, and never in your return data. The most common ones, drawn from the e-Services API Authorization User Guide §4, fall into a handful of recognizable patterns.
| HTTP | Code | Meaning | Most likely cause & fix |
|---|---|---|---|
| 401 | ESRV201 | invalid_client | Client credentials not recognized. Confirm the API Client ID is active and matches the JWT sub. |
| 401 | ESRV202 | login_required | Resource owner not authenticated. The tax professional must complete e-Services login and consent. |
| 401 | ESRV205 | cert not valid | Client certificate invalid or expired. Renew the certificate and re-sync the JWKS. |
| 401 | ESRV306 | invalid_client (JWT) | The client-auth JWT is malformed or signed wrong. Check the kid matches the JWKS and alg is RS256. |
| 401 | ESRV709 | invalid_scope | The key lacks a required scope. The token must carry iris (and tinm for TIN Matching). |
| 401 | ESRV725 | token disabled | Validation error — the token has been disabled. Re-mint a fresh access token. |
| 403 | ESRV203 | SSL required | The request hit a non-TLS endpoint. Use the HTTPS host only. |
| 403 | ESRV204 | mTLS required | SSL with client authentication required. Present your client certificate, not just server TLS. |
| 429 | ESRV111 | rate limit | Call limit exceeded; a 10-minute blackout now applies. Back off and retry after the window. |
| 500 | ESRV711 | consent error | Access denied. The tax professional has not granted, or has revoked, consent to your A2A Client ID. |
Two of these account for most of the support tickets, and both reward a careful look because the symptoms are easy to misread. The first is ESRV204, which looks like a generic connection failure but is really the gateway insisting on mutual TLS. The second is ESRV306, the catch-all for a client-authentication JWT that the gateway will not accept.
Cause: the IRS endpoint demands SSL with client authentication, and your client presented server-side TLS only, so the gateway never authenticated your certificate. Fix: configure mutual TLS and present the same client certificate whose public key sits in your registered JWKS. An empty-bodied 401 or 403 at this stage usually means the request was rejected at the gateway before the API ever saw it, which is also the classic symptom of hitting the wrong host — the TIN Match path, for instance, uses a different host than the IRIS transmission path.
Cause: the JWT you sign for client authentication is rejected, almost always because the kid in the header does not match your JWKS (it is case-sensitive), the signing algorithm is wrong, or the token has simply expired — the access token has only a fifteen-minute lifetime. Fix: sign with RS256, set the header kid to the exact value registered in your JWKS, and include every required payload claim: iss, sub, aud, iat, exp, and the mandatory jti that prevents replay. Remember that IRIS expects two distinct JWTs — a Client JWT and a User JWT — so a 306 can also mean you supplied the wrong one.
POST /auth/oauth/v2/token
HTTP/1.1 401 Unauthorized
{
"error": "ESRV306",
"error_description": "invalid_client (JWT invalid)"
}
--- after fixing the kid + algorithm ---
POST /auth/oauth/v2/token
HTTP/1.1 200 OK
{
"access_token": "eyJhbGciOiJSUzI1...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "esrv-alt sor tinm iris"
}The contrast above is the whole pattern in miniature: the gateway returns a JSON body naming the ESRV error on failure, and once you correct the underlying credential the very same request returns a bearer token whose scope includes iris. That token is what IRIS will accept on the transmission call — nothing about your return changed.
Layer 2 — A Pre-Receipt 400 Means Nothing Was Saved
Once you are authenticated, you POST your transmission to the intake-acceptance endpoint, and IRIS runs what Pub 5718 calls Phase 1 validation synchronously. This is a fast structural pass: it confirms the manifest is present, checks that the transmission actually contains submissions, and verifies the test-or-production code. If any of those checks fail, you get an HTTP 400 and — this is the part that trips people up — no Receipt ID is issued at all. Because nothing was saved, there is nothing to replace; the corrected file must be resent as an Original. These are the Table 6-1 errors from Pub 5718.
| Error | Cause | HTTP body hint |
|---|---|---|
| Duplicate UTID | Same UniqueTransmissionId resubmitted | "Unable to process request, check for duplicate data" |
| Test code to PROD | TestCd="T" sent to production | "Found invalid Test Code, found T, P is required" |
| Bad test code | TestCd is neither T nor P | "Unable to process request, check Test Code" |
| Missing manifest | Manifest absent from the transmission | "Unable to process request" |
| No submissions | Empty transmission, zero submissions | "Unable to process request" |
| Schema validation error | Manifest XML structurally invalid | "Unable to process request" |
There is one wrinkle worth internalizing before you build any retry logic. Per Pub 5718, a transmission that is rejected for an XML Schema Validation Error does receive a Receipt ID, even though every other Phase 1 failure does not — but that Receipt ID cannot be used to file a Replacement. The corrected file still has to be resent as an Original. The safe mental model is to treat a schema-validation failure as never filed, regardless of whether a Receipt ID came back, so your code never tries to attach a Replacement to a transmission the IRS will not let you replace.
An HTTP 429, which surfaces as ESRV111 on the authentication side, means you exceeded the gateway's call limit and a ten-minute blackout is now in effect. There is no faster path through it — backing off for the full window is the only fix, and hammering the endpoint only extends the pain. The same anti-abuse posture governs interactive TIN Matching, where four mismatched attempts on the same name-and-TIN pair suspend access for ninety-six hours, so it pays to pre-validate before you call rather than discovering the limit the hard way.
Layer 3 — Business-Rule Codes Carry the Failing Element
If your transmission cleared Phase 1 you received a Receipt ID, and IRIS then runs Phase 2 validation asynchronously against the full business-rule catalog. You poll the status-and-acknowledgement endpoint and parse the result. The valuable thing about a Phase 2 error is that it is never just a code: each failing rule arrives inside an <ErrorInformationGrp> with four fields, and the last of them tells you the exact XML element to fix.
<n1:RecordResultGrp>
<n1:RecordId>1</n1:RecordId>
<n1:ErrorInformationGrp>
<n1:ErrorMessageCd>S1H022</n1:ErrorMessageCd>
<n1:ErrorMessageTxt>If FormTypeCd is 1099R, then Form1099RTotalAmtGrp must be present.</n1:ErrorMessageTxt>
<n1:ErrorValueTxt>1099R</n1:ErrorValueTxt>
<n1:ElementPathTxt>/IRTransmission/.../IRSubmission1Grp/IRSubmission1Header</n1:ElementPathTxt>
</n1:ErrorInformationGrp>
</n1:RecordResultGrp>That is the real shape of the TransStatusOrAckResponse from the IRIS Status Library. The ErrorMessageCd carries the rule ID, the ErrorMessageTxt restates the rule in plain language, the ErrorValueTxt echoes the offending value, and the ElementPathTxt points straight at the element that failed. Read the path, fix that element, and refile — you rarely have to guess.
The rule ID itself encodes which level of the document failed, so the prefix alone narrows your search before you even read the message. A TMFST prefix points at the transmission and manifest level — your TCC, SoftwareId, UniqueTransmissionId, and the various counts. An SMF prefix points at the shared submission level, covering tax year, the issuer's TIN and name, and form authorization. An S1H prefix points at the Submission-1 header, where the per-form total-amount groups and the CF/SF election live. And a SHAREDIRFORM prefix points at the record level, where recipient name and TIN matching, addresses, and corrections are checked.
| Rule ID | What it checks | Severity | Fix |
|---|---|---|---|
| TMFST002_001 | TransmitterControlCd must match your TCC in the IRS database. | Reject | Send the exact TCC tied to your IR Application. |
| TMFST020 | The first two digits of SoftwareId must match the last two digits of TaxYr. | Reject | Use the SoftwareId issued for that tax year. |
| TMFST032 | The UniqueTransmissionId must carry the A2A channel suffix. | Reject | Build the UTID with the ::A channel suffix. |
| TMFST026 | TotalIssuerFormCnt must equal the issuer count in the transmission. | Reject | Recompute the manifest count after assembly. |
| SMF007 | The submission TaxYr must match the manifest TaxYr. | Reject | Align the tax year across manifest and submissions. |
| SMF029 | FormTypeCd must be authorized for your TCC. | Reject | Add the form type to your IR Application roles. |
| S1H022 | If FormTypeCd is 1099R, Form1099RTotalAmtGrp must be present. | Reject | Emit the matching total-amount group for the form type. |
| S1H002 | If CFSFElectionInd = 1, the TCC must participate in CF/SF. | Report Error | Enroll the TCC in Combined Federal/State Filing first. |
| SHAREDIRFORM023 | The TIN in RecipientDetail must have a value. | Report Error | Populate the recipient TIN before filing. |
| SHAREDIRFORM014 | PersonName plus TIN must match the IRS database. | Report Error | Run TIN Matching first; fix the name control. |
| SHAREDIRFORM021 | If TestCd = T, the recipient TIN must start with 000. | Reject | Use 000-prefix fictitious TINs in ATS only. |
The severity column is the difference between fix-now and fix-later, and it changes what you owe the IRS. A Reject-severity rule stops the submission cold: nothing is filed until you correct it and resend. A Report Error-severity rule lets the return through as Accepted with Errors, meaning the form is on file but flagged, and you resolve it afterward with a correction. Some rules carry a hybrid posture, "Report Error and Reject if Over Threshold," where too many instances of the same error across one submission escalate the whole thing to a hard reject — which is why a single sloppy data field, repeated across thousands of records, can sink an otherwise clean batch.
Three Rejections That Reward a Closer Look
A handful of rules generate far more confusion than the rest, usually because the fix is not obvious from the message alone. These three are worth understanding in full, because getting them wrong tends to produce a second rejection rather than a fix.
Cause: the tail of your UniqueTransmissionId does not carry the A2A channel marker, so IRIS cannot route the transmission to the right channel. Fix: build the UTID in the exact form <UUID>:IRIS:<TCC>::A — for example da20a4de-1357-11ed-861d-0242ac120002:IRIS:DH96S::A. The TCC embedded inside the UTID must also equal your TransmitterControlCd, or you will trip a second, separate reject on the cross-check.
Cause: for a Replacement transmission (TransmissionTypeCd="R") you supplied both an OriginalReceiptId and an OriginalUniqueSubmissionId, or the receipt you pointed at refers to a transmission that was already successfully replaced. Fix: supply exactly one key. Use OriginalReceiptId to replace a whole transmission, or OriginalUniqueSubmissionId in the submission header to replace a single submission — never both. The receipt you reference must be a rejected Original that has not already been replaced; if it has, there is nothing left to replace and you should file fresh.
Cause: the recipient's PersonName (or BusinessName) plus TIN does not match IRS records. This is Report-Error severity, so the form is Accepted with Errors rather than rejected — but it is the leading cause of the CP2100 "B-notice" letters that land months later. Fix: run free IRS TIN Matching before you file, and respect the XML name rule while you are at it: PersonFirstNm, PersonMiddleNm, and PersonLastNm may not contain any special character even when escaped, so O'Malley must be written as OMalley. A # is permitted in BusinessNameLine1Txt but never in a person-name field.
What Each Transmission Status Tells You to Do Next
Every acknowledgement carries an overall status, and that status is your instruction for what to do next. The distinction that matters most in production is between a status that needs a Replacement and one that needs a correction, because confusing the two is how filers accidentally duplicate-file or, worse, leave a flagged return unaddressed until the IRS notices for them.
| Status | Meaning | Your next move (production) |
|---|---|---|
| Accepted | Successfully processed, no errors | Nothing — you are filed. |
| Accepted with Errors | Processed, Report-Error rules flagged | File a correction (one-step or two-step). |
| Partially Accepted | Some submissions accepted, some rejected | Replace only the rejected submissions. |
| Rejected | A Reject-severity rule fired; errors listed in the ack | Replace the transmission (or resend an Original if it was a schema error). |
| Processing | Phase 2 is not yet complete | Wait and re-poll the acknowledgement endpoint. |
| Not Found | Receipt ID or UTID could not be located | Re-check your search ID; searching by UTID returns the Receipt ID. |
Common Rejection Reasons (and How to Avoid Them)
Most production rejections are not exotic. They cluster around a few predictable mistakes that surface the moment a transmission leaves a clean ATS sandbox and hits real data at volume. The four below account for the bulk of avoidable rejects, ordered by how often they bite.
Cause: a recipient's name control and TIN disagree with the IRS database, tripping SHAREDIRFORM014. Because it is Report-Error severity the batch is still accepted, so the problem hides until it returns as a CP2100 notice. Fix: run IRS TIN Matching on every recipient before you transmit, and strip apostrophes, hyphens, and other special characters out of person-name fields where the schema forbids them.
Cause: a transmission still carries TestCd="T" when it hits the production endpoint, or a record uses a fictitious 000-prefix TIN outside ATS, tripping the intake 400 or SHAREDIRFORM021. Fix: gate the test flag behind your environment configuration so production builds always send P, and reserve 000-prefix recipient TINs strictly for the Assurance Testing sandbox.
Cause: the TotalIssuerFormCnt in the manifest no longer matches the assembled submissions (TMFST026), or a submission's TaxYr disagrees with the manifest's (SMF007). These slip in when records are added or dropped after the manifest is built. Fix: compute the counts and stamp the tax year as the very last step before signing, never before, so the manifest always describes the file you are actually sending.
Cause: the UniqueTransmissionId is missing its ::A channel suffix (TMFST032), the TCC embedded in the UTID does not match TransmitterControlCd, or a form type was sent that your TCC is not authorized for (SMF029). Fix: assemble the UTID from a fresh UUID, the literal IRIS token, and your exact TCC with the ::A suffix, and confirm every form type you transmit is enabled on your IR Application roles.
Skip the Decoding Entirely
Tired of decoding rejection codes by hand?
e1099f validates every record against the full IRS business-rule catalog before you transmit, so you get a Receipt ID instead of a rule code to chase.
Pre-validated
Records are checked against the rule catalog before submission, so reject-severity rules are caught at your desk, not at the IRS.
Errors by element
The acknowledgement is parsed for you and each error is surfaced by its ElementPathTxt, pointing straight at the field to fix.
Auth handled
The mutual-TLS connection, the signed JWTs, and the token scopes are managed for you, so ESRV codes stop being your problem.
A Receipt ID, not a rejection — across every layer and every form type.
Frequently Asked Questions
I got an ESRV code — is my XML wrong?
What's the difference between "Reject" and "Report Error"?
I got a 400 with no Receipt ID. Can I replace the file?
Where do I find the exact element that failed?
<ErrorInformationGrp> carrying ErrorMessageCd (the rule ID), ErrorMessageTxt (the rule text), ErrorValueTxt (the offending value), and ElementPathTxt (the path to the failing element). Read the path, fix that element, and refile.Why did my recipient's name get rejected even though it looks right?
PersonFirstNm, PersonMiddleNm, PersonLastNm) cannot contain any special character, even an escaped one, so an apostrophe in O'Malley must be stripped to OMalley. Separately, a name and TIN that don't match IRS records trip SHAREDIRFORM014; running TIN Matching first avoids it.What does the rule-ID prefix tell me?
TMFST prefix points at the transmission and manifest level, where your TCC, SoftwareId, UTID, and the various counts are checked. An SMF prefix points at the shared submission level, covering the tax year, the issuer's TIN and name, and form authorization. An S1H prefix points at the Submission-1 header, where the total-amount groups and the CF/SF election live. And a SHAREDIRFORM prefix points at the record level, where recipient name and TIN, addresses, and corrections are validated.What does an HTTP 429 mean, and how do I clear it?
ESRV111 on the auth side) means you exceeded the gateway's call limit and a ten-minute blackout is now in effect. There is no faster path — back off for the full window. For interactive TIN Matching the related limit is four mismatched attempts on the same name and TIN, which suspends access for ninety-six hours.What's the difference between a Replacement and a correction?
Why did my CF/SF election get flagged?
CFSFElectionInd = 1 but your TCC is not enrolled in the Combined Federal/State Filing program, you trip S1H002. Enroll the TCC in CF/SF first. Note also that CF/SF participation has to be established before you elect it on a submission — the election alone does not enroll you.Does my whole batch fail if one record is bad?
Does e1099f require me to understand any of these codes?
ESRV or SHAREDIRFORM codes by hand to file.Not tax advice. This is general information about IRS IRIS procedures and error handling. The IRS may change IRIS, its schema, and its business rules as the system evolves, and the published IRS publications and the current rule catalog are authoritative. Consult a tax professional for your specific situation.