My printer stopped. Not broke — stopped. The panel showed E-11, “The ink pad needs service”, and it refused to print. It also refused to scan, which is the detail that turned this from a repair job into something worth writing about. The scanner has no ink path and no waste pad. There is no technical reason for a full ink sponge to disable a scanner.
This is how I fixed it for €0, and — the part I actually care about — how I proved the fix was safe before doing it.
What E-11 actually is
It is not a failed part. Inside the printer is a felt sponge that soaks up ink wasted during head cleaning and power-on flushes. Epson does not measure how full it is. Instead the firmware keeps a counter in EEPROM, adding an estimated amount every time it flushes. When that counter hits a factory limit, the machine locks itself.
The sponge is usually nowhere near saturated. Mine, judging by the other printers I have opened over the years, was at most half full.
Here is what my printer actually reported, before anything was written to it:
MDL (printer's own self-report) : ET-2650 Series Serial : X2PG208272 Waste counter : 6207 / 6207 = 100.00 % Ink levels : -1% (EcoTank has no level sensors)
Exactly at the ceiling. That is the lock, on my machine, as a number.
Replacing the pad does not work
The natural assumption is: the pad is full, so replace the pad. It does not work, and the reason is worth being precise about.
A teardown by BCH Technologies demonstrates it on the sibling ET-2760: they bought Epson’s replacement waste tank, fitted it, restarted — and E-11 was still there. Put side by side, the replacement part carries a chip and the original does not.
The count lives in the printer, not in the part. A fresh sponge changes nothing the firmware can observe. Only a write to the printer’s own memory moves that number. So the fix is necessarily a software one.
The route I refused to take
Search for this problem and every result funnels you to the same place: download a resetter .exe, then buy a key for about $10.
No thanks, for two reasons.
The malware problem. The “Epson resetter” search space is one of the dirtier corners of the web. Sites like wic.support, resetkey.net, inkchip.net and assorted mirrors distribute compiled binaries that talk directly to hardware, and the genre is notorious. I did not want an unauditable binary on my machine with permission to write to device memory.
The principle. Paying €10 to unlock a working machine rewards the behaviour.
Two free tools run from readable source:
- epson_print_conf — Python, talks SNMP over the network
- ez-reset — Python, talks D4 over USB
I installed both from source. No prebuilt binaries — ez-reset ships one in its Releases tab and I deliberately skipped it and cloned the repository instead. Defender scanned the folder: clean. Nothing installed system-wide, nothing at boot.
A detour: the printer that would not answer
The network route died first. The printer was powered on but silent at layer 2 — Windows’ IPv6 neighbour cache reported it Unreachable while the router on the same link answered normally. It never finished booting far enough to bring its network stack up. So: USB cable, and ez-reset.
One more obstacle worth recording, because it is a nice example of a tool lying about its own failure. epson_print_conf refused to start on Python 3.14 with the message invalid address: There is no current event loop. It has nothing to do with the address. Deep in pysnmp, asyncio.get_event_loop() is called; Python 3.12 deprecated it and 3.14 made it a hard error. The tool builds its dispatcher inside a broad except Exception and blames the address.
Lesson: when a tool reports a cause, check that it is not just the outermost exception handler talking.
The part that actually mattered: verifying before writing
This is the difference between “I ran a tool” and “I knew what I was doing”.
ez-reset is a small graphical program: pick your printer, look at the bars, press Reset All. I did not press it. Every piece of it is importable, so I drove it from my own script instead — read-only first.
The problem I had to solve first
Both tools identify this printer by mapping it onto another model’s memory layout, and they disagreed about which:
epson_print_conflists ET-2650 as an alias of ET-2600 / L395- Epson’s own device database inside ez-reset says ET-2600 = L395 but ET-2650 = L495 — two different models
Writing to EEPROM using the wrong model’s map is exactly how you turn a locked printer into a dead one. I was not willing to guess.
Three independent proofs that the map was right
Proof one — the serial matches across two channels. The printer’s IEEE-1284 identity string contains SN:583250473230383272. That hex is ASCII: 58=X, 32=2, 50=P, 47=G… spelling X2PG208272. Reading the serial through the status/EEPROM channel returned the same string. Two independent paths agreeing means the read key is correct — so the 6207 is a real number, not garbage.
Proof two — the serial is where it should be. I dumped 2048 bytes and searched for it. It sat at address 192. epson_print_conf documents the ET-2600 serial as range(192, 202). So the layout matches, not merely the key.
Proof three — the arithmetic closes. Addresses 24 and 25 held 63 and 24. Little-endian: 24 × 256 + 63 = 6207 — precisely the counter value and precisely its maximum. Those two bytes are the counter, confirmed by arithmetic rather than by trust.
The reset map, checked against two sources
The reset writes six bytes. Both projects agree completely:
| Address | Before | After | What it is |
|---|---|---|---|
| 24, 25 | 63, 24 | 0, 0 | the waste counter (6207) |
| 28, 29 | 205, 41 | 0, 0 | second related counter (10701) |
| 30 | 0 | 0 | already zero |
| 46 | 104 | 94 | not a counter — the threshold |
Address 46 is the one that made me stop. Why write 94 and not 0?
epson_print_conf carries a comment naming it: “Maintenance required level of 1st waste ink counter”. It is the trigger level, and on my printer it had drifted to 104. The neighbouring byte, address 47, is the second counter’s threshold and already held exactly 94 — the untouched factory value. Writing 94 to address 46 restores it to match its own neighbour.
That is not an off-by-one. It is confirmed from three directions: two independent projects, a documenting comment, and the adjacent byte.
Reading the raw database entry
I did not trust the parser either. Epson’s devices.xml, under the L495 node:
0x18 0x00 0x19 0x00 0x1E 0x00 0x1C 0x00 0x1D 0x00 0x2E 0x5E
Parsed as address/value pairs: 24→0, 25→0, 30→0, 28→0, 29→0, 46→0x5E = 94. The parse was correct. Only one spec node in the chain contributes a reset block, so there was no ambiguity about which definition wins.
Hand-decoding the actual command
Finally I dry-ran the write and decoded one command byte by byte. Twenty bytes to set address 24 to zero:
7c 7c 10 00 10 08 42 bd 21 18 00 00 54 6a 6f 62 63 76 6f 68
| Bytes | Meaning |
|---|---|
7c 7c | “||” — the factory command prefix |
10 00 | payload length, 16, little-endian |
10 08 | the model code |
42 bd 21 | action 0x42 plus its checksum pair |
18 00 | address 24, little-endian |
00 | the value to write |
54 6a 6f 62 63 76 6f 68 | the write key, ASCII “Tjobcvoh” |
The checksum triple checks out by hand: 0x42 XOR 0xFF = 0xBD, and (0x42 >> 1) AND 0x7F = 0x21.
A small aside that pleased me: Tjobcvoh is Sinabung with every letter shifted up by one. Epson’s habitual light obfuscation — and the same key epson_print_conf carries under a different name. Two tools, arrived at independently, holding the same secret.
Ten things that had to be true first
I wrote my own script rather than pressing somebody else’s button, so the checks could be built in:
- Full 2048-byte EEPROM backup — not just the six bytes
- Address whitelist — refuses any address outside the verified six
- Value whitelist — refuses any value other than the verified ones
- Map assertion — aborts if the database disagrees with the hand-verified map
- Live-vs-backup cross-check — aborts if the EEPROM drifted since the backup
- Serial canary — read before and after; a change means abort
- Write, then read back, every byte — first mismatch aborts
- The first write doubles as a key test — a wrong key is silently ignored by the printer, so the read-back would still show the old value and we stop with zero bytes changed
- Counter bytes first, threshold last — an abort part-way leaves the printer no worse off
- An undo mode, written and rehearsed before the write
That last one is the habit most worth passing on: build the undo before you build the do, and then actually run it. Because every target byte still held its original value, the undo path could be executed end-to-end as a live rehearsal — it connected, ran every check, took the write branch, correctly skipped all six bytes, and confirmed the serial was stable. The recovery path was proven working before it was needed.
I rejected one idea: test-writing to a scratch address first. There is no known-safe scratch byte on this EEPROM, so that would have added risk rather than reduced it.
And a naming note that nearly cost me. I first called the undo --restore. That reads like “restore the printer to working order” when it means the exact opposite: put the lock back. It is now --relock, and it refuses to run without an explicit --confirm. Names are safety equipment.
The write
Six commands, about two seconds:
addr 24 : 63 -> 0 verified addr 25 : 24 -> 0 verified addr 28 : 205 -> 0 verified addr 29 : 41 -> 0 verified addr 30 already 0 - skipped addr 46 : 104 -> 94 verified serial canary (after): X2PG208272 STABLE waste counter now: 0 / 6207 = 0.00%
Then a power-cycle from the printer’s own button. It prints. It scans.
One measurement worth having, which almost nobody publishes because almost nobody can read the counter: the power-on flush plus a single test page cost 124 units — 2% of the entire pad budget. Every power cycle is not free. Neither is every head cleaning. If you are the sort of person who runs three cleaning cycles in a row out of impatience, that is roughly what it costs you.
What the reset does not fix
Every one of these tools warns you, and the warning is fair: resetting the counter removes a lock; it does not empty the sponge.
I chose not to touch mine. I have opened enough printers to judge that it is at most half full, and this one sits on a desk where a leak would be obvious long before it became a problem.
If you do want the permanent fix, the numbers from the ET-2760 teardown are useful: a full waste tank weighed about 100 g more than a new one, so budget roughly 100 ml of accumulated ink and a bottle of at least 200 ml. Epson has already moulded a circular knockout in the side plate for the tube, so no drilling is needed. And the Velcro in those kits only stops the bottle being knocked over — it is not a mount. People who hung the bottle off a desk edge found it on the floor the next morning.
Is any of this legal?
Resetting your own out-of-warranty printer: yes. It is your device, no copyright protection measure is involved, and the only thing you can lose is a warranty that has already expired.
The more interesting question is whether what Epson did is legal.
- Germany: no law against planned obsolescence. The two-year Gewährleistung runs against the seller, not Epson, and has long expired on a 2016 printer. Today there is no claim to bring.
- France: Epson stood trial at Nanterre on 2 July 2026 — the first case of its kind in the world, after a complaint by the NGO HOP and eight years of investigation. The prosecutor’s charge explicitly names ink pads blocked by a counter. Pleadings are set for 25 February 2027.
- EU, from 27 September 2026: Directive (EU) 2024/825 blacklists as always-unfair “inducing the consumer to replace or replenish the consumables of a good earlier than necessary for technical reasons”, and features introduced to limit durability.
- Right to Repair (EU 2024/1799): does not cover printers — they are not in Annex II.
So the behaviour that stopped my printer is the exact behaviour a European prosecutor has taken to criminal court. Not yet a conviction — but not nothing either.
What generalises beyond printers
On the printer: a replacement pad cannot fix E-11, because the count is in the machine, not in the part. Free tools exist that run from source. You do not need to pay €10 or run a stranger’s binary.
On the method — and this is the part that applies to code as much as to hardware:
- When two sources disagree about a fact you are about to act on, do not average them and proceed. Find a third thing that only one of them predicts, and test that. The serial at address 192 settled a question that no amount of re-reading either project’s source could have.
- Verify with arithmetic that has to close. 24 × 256 + 63 = 6207 was worth more than any documentation.
- A magic constant that looks wrong deserves a stop. Writing 94 instead of 0 looked like a bug until the neighbouring byte explained it.
- Build the undo first, and rehearse it. Then name it so nobody mistakes it for a repair.
- Read the payload you are about to send. Twenty bytes, decoded by hand, cost five minutes.
The counter is a business decision dressed as a maintenance warning. The scanner lock gives it away. But the fix is fifteen minutes of careful work — and the careful part is not the writing. It is everything before it.