Skip to content

Fix NFC tag writing always reporting failure - #100

Open
qoncept96 wants to merge 1 commit into
drndos:mainfrom
qoncept96:fix/nfc-write-false-failure
Open

qoncept96 wants to merge 1 commit into
drndos:mainfrom
qoncept96:fix/nfc-write-false-failure

Conversation

@qoncept96

Copy link
Copy Markdown

Problem

Writing a tag reports failure even when the write succeeds. The message is:

❌ Write failed. Please try again: AbortError: push is canceled due to a new push request

Web NFC allows exactly one pending push per document. writeNFC()
(templates/write_tag.html:45) builds a fresh NDEFReader and calls write() on
every button press:

  1. First press starts a push, which waits for a tag to enter the field.
  2. Nothing appears to happen, so the user presses again.
  3. The second write() aborts the first, and the first promise rejects with
    AbortError.
  4. That rejection is what fills the message box — so the UI says "failed" while
    the second push is usually still live and about to succeed.
  5. The user presses again. Repeat forever.

The tag frequently does get written; the UI just never says so.

This is client-side only and unrelated to cloud vs LAN — it affects any Android
Chrome user.

Fix

One reusable NDEFReader, one in-flight write tracked in pendingWrite, and a
second press becomes an explicit AbortController cancel rather than a competing
push. AbortError is reported as "cancelled", not "failed". The button doubles as
Cancel while a write is pending, so the state is visible.

Full diff in the PR; the shape is:

let ndefWriter = null;
let pendingWrite = null;

if (pendingWrite) { pendingWrite.abort(); return; }   // explicit cancel
ndefWriter = ndefWriter || new NDEFReader();
pendingWrite = new AbortController();
ndefWriter.write({records: [...]}, {signal: pendingWrite.signal})
  .then(...)
  .catch(e => e?.name === "AbortError" ? cancelled() : failed(e))
  .finally(() => { pendingWrite = null; restoreButton(); });

Testing

Running in production since 2026-08-30, verified by hand on a Pixel with Chrome
over https: first press waits, tapping the tag writes and now reports success;
pressing again mid-wait reports "cancelled" instead of "failed" and leaves the
reader reusable for the next attempt.

Web NFC needs a secure context, so this is untestable over a plain-http LAN URL —
that path is unchanged ('NDEFReader' in window is false and the existing
unsupported-browser message shows).

Web NFC allows one pending push per document. writeNFC() built a fresh
NDEFReader and called write() on every button press, so:

  press 1 starts a push and waits for a tag
  nothing visibly happens, so the user presses again
  press 2 aborts press 1
  press 1's promise rejects with "AbortError: push is canceled due to a
  new push request" -- and that rejection is what fills the message box

The UI says the write failed while press 2 is still live and usually
about to succeed, so the user keeps pressing and the tag often does get
written without ever being reported.

Keep one reusable NDEFReader and one in-flight write. A second press is
now an explicit AbortController cancel rather than a competing push, and
AbortError is reported as cancelled rather than failed. The button shows
Cancel while a write is pending so the state is visible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant