Skip to content

Est. 2011ยทMicrosoft Partner 7033487ยทDelivery under 3 minยทSupport 7 days a week

Your vault is empty.

Free Fix 20598

Error 20598: The Row Was Not Found at the Subscriber When Applying Commands

9 min read Updated October 4, 2026 SQL Server

Fix it now

Error 20598 is published as the row not being found at the Subscriber when applying a replicated command for a named table, with the primary keys printed in the message. Transactional replication ships commands rather than rows, so a command that targets a missing row has nowhere to land. The fix is to find out how the copies drifted, not to skip errors forever.

Run at the Distributor, on the distribution database, with the sequence numbers from the agent error

USE distribution;
EXEC sp_browsereplcmds
     @xact_seqno_start = '0x0000000000000000',
     @xact_seqno_end   = '0xFFFFFFFFFFFFFFFF';
  1. Open Replication Monitor, find the failing subscription and read the error detail. It gives you the transaction sequence number and the command id, and the 20598 message itself prints the table and the primary key values.
  2. Narrow the call above to that sequence number range and match the command_id column to the command id from the error. That gives you the exact statement the agent is trying to apply.
  3. Query the Subscriber for that key and confirm the row really is absent, then query the Publisher for the same key so you know what should be there.
  4. Ask why it is absent before doing anything: a local purge job, a direct write, or an initialisation that did not match are the three usual answers.
  5. Reconcile properly, by validating the article and reinitialising just that article, rather than leaving the agent skipping errors indefinitely.

Microsoft’s documented quick remedy for a single known row is to insert it at the Subscriber so the Distribution Agent can retry the failed command. That is first aid: it does not tell you why the row went missing.

If the agent runs clean and validation agrees, stop here. If it fails again next week, the next section covers where the drift comes from.

Why it happens

The Log Reader Agent turns committed changes at the Publisher into commands, and the Distribution Agent replays them at the Subscriber. Nothing in that pipeline compares the two copies as it goes. An update or a delete is applied by key, so if the row with that key is not there, the command has nowhere to land and the agent stops. The message names the table and prints the primary keys, which is more help than most replication errors give you.

Drift comes from a small number of places. Somebody writes directly at the Subscriber, deliberately or through an application nobody remembered was pointed there. A retention or purge job runs locally and removes rows replication still expects. The subscription was initialised from a backup or by hand and the starting point did not match. Or errors were skipped in the past, so commands were dropped and every later command that depended on them now fails.

Error 2601 is the same problem seen from the other end. Its published text is that a duplicate key row cannot be inserted into the named object with the named unique index, and it prints the duplicate key value. An insert arrives for a key that already exists at the Subscriber and the unique index rejects it. When you see 20598 and 2601 alternating in one subscription, treat it as a single drift problem rather than two.

One more thing is worth knowing before you start changing data: the two copies can be compared properly. The tablediff utility is current, ships with the replication feature, and is documented as comparing rows between a source table at a Publisher and destination tables at Subscribers, with the option to generate a Transact-SQL script that brings the destination into convergence. It is a better starting point than reading rows by eye.

Something writes to the Subscriber

You have this one if The missing rows belong to one or two tables, and somebody has more than read rights on the subscription database.

  1. Find the writer: local jobs, ETL packages, and applications whose connection strings point at the Subscriber.
  2. Remove write permissions from anything that should be read-only, so the subscription database cannot drift again.
  3. Validate the affected articles, then reinitialise the ones that no longer match.

If an application genuinely has to write to those tables, replication is the wrong tool for them. Exclude them from the publication rather than fighting the same failure every week.

A local retention job deletes rows

You have this one if Failures appear on a schedule, always affecting older rows, and a purge or archive job runs at the Subscriber.

  1. Stop the local purge and let the deletes arrive through replication from the Publisher instead.
  2. If the Subscriber must hold less data than the Publisher, use a filtered article so the boundary is part of the publication.
  3. Reinitialise the affected article once the purge is disabled.

The subscription was initialised from a mismatched starting point

You have this one if Errors began immediately after the subscription was set up from a backup or with a manual copy of the data.

  1. Validate the publication at the Publisher: EXEC sp_publication_validation @publication = N'YourPublication';
  2. For a small number of tables, reinitialise the individual articles rather than the whole subscription.
  3. For widespread differences, reinitialise the subscription and apply a fresh snapshot during a quiet period.

Errors have been skipped for a long time

You have this one if The agent runs with a profile that continues past data consistency errors, and nobody can say when the copies last matched.

  1. Check the agent profile and any parameter listing error numbers to be ignored, and record what it has been skipping.
  2. Compare the two copies with tablediff and keep the script it generates as evidence of how far apart they were.
  3. Plan a reinitialisation, then remove the skip setting so future drift is visible immediately.

Full reference

Reading the evidence

What you find What it points at
Failures in one table only A local job or an application writing to that table at the Subscriber
Failures across many tables at once The initialisation did not match, or errors were skipped earlier
20598 and 2601 alternating Rows are being deleted and reinserted locally at the Subscriber
Failures start after a maintenance window A restore, a purge or a manual correction at the Subscriber
The key in the message is one you recognise Go straight to whoever owns that data before touching replication

Finding the command behind the error

  1. Take the transaction sequence number and command id from the agent’s error detail in Replication Monitor.
  2. Run sp_browsereplcmds at the Distributor, on the distribution database, narrowed to that sequence range.
  3. Match the command_id column in the results to the command id from the error.
  4. Read the command column, which is the Transact-SQL the agent is trying to apply, and note the article_id.
  5. Use that article id to identify the table at the Publisher and validate it.

Validation options, and what each costs

@rowcount_only What it does
1 (default) Row count comparison only. Cheap, and catches most drift
0 Checksum comparison compatible with older versions
2 Row count and binary checksum. The thorough option, and the slowest

sp_publication_validation runs at the Publisher on the publication database and raises a validation request for every article in the publication. Run it before and after a reconciliation so you have a before-and-after rather than an impression.

tablediff, used properly

  • It ships with the replication feature, and in SQL Server 2022 lives in the COM folder under the instance’s installation path.
  • It can compare row counts and schema quickly, or go column by column.
  • It can generate a Transact-SQL script that brings the destination into convergence, which is the output worth keeping.
  • Read that script before you run it. It is a record of exactly how far apart the copies had drifted, and it is the argument for fixing the cause.

Telling the agent to continue past these errors does not repair anything. It discards the failed commands permanently, so the Subscriber falls further behind with every skip and the eventual reconciliation gets larger. Microsoft documents the skip parameter as a way to keep the rest of the changes flowing while you deal with the referential integrity question, not as a standing configuration.

Every code this article covers

Code What it points at Source
20598 The row was not found at the Subscriber when applying the replicated command for the named table, with the primary keys printed in the message Microsoft Learn
2601 Cannot insert a duplicate key row into the named object with the named unique index; the duplicate key value is printed Microsoft Learn

Confirm the fix worked

  1. Article or publication validation reports that row counts, and checksums if you used them, agree.
  2. The Distribution Agent runs to completion with no errors in its history.
  3. An insert, update and delete of a test row at the Publisher arrives at the Subscriber.
  4. No error-skipping parameter remains on the agent profile.
  5. Nothing other than replication holds write permission on the subscription database.

Questions people ask about this

Can I just insert the missing row by hand?

For a single known row it is a legitimate stopgap, and Microsoft documents it: insert the missing row at the Subscriber so the Distribution Agent can retry the failed command. It does not tell you why the row went missing, so treat it as first aid.

Does reinitialising mean copying the whole database again?

Not necessarily. You can reinitialise a single article, which drops and recreates just that table at the Subscriber from a new snapshot. That is far cheaper than a full snapshot of a large publication.

Is this a licensing or edition problem?

No, and it costs nothing to fix. It is a data consistency problem between two copies. Worth knowing separately: SQL Server Express can act as a subscriber but not as a publisher or distributor.

Is tablediff still available?

Yes. It is documented as current, ships with the replication feature, and can generate a Transact-SQL script to bring the destination into convergence rather than only reporting the differences.

How do I stop it happening again?

Keep the subscription database read-only for everything except replication, make sure no local job deletes or reshapes replicated tables, and validate articles on a schedule so drift is found while it is still small.

Related error codes

Was this article helpful?

Your feedback helps us improve our documentation.

Related articles

License Error SSIS Error 0xC0047062: Packages Fail as Agent Jobs but Run in Visual Studio Free Fix Error 7391: The Linked Server Could Not Begin a Distributed Transaction Free Fix Error 8992 and CHECKCATALOG Failures: System Metadata Is Inconsistent License Error Error 8645: Memory Grant Timeouts Against the Standard Edition Memory Cap
โ† Back to Knowledge Base