Artifact publish permanently refused as "resent unchanged" after a viewed-check rejection, even once the artifact has been re-read in full (no capabilities, single writer)
Summary
An Artifact publish to an existing artifact was refused once for "you hadn't viewed the live version". After satisfying the documented recovery flow — Artifact action:"read" on the URL, then Reading every line of the saved source file it names — every subsequent publish of that same (edited) payload is refused with a different message:
Publish refused — nothing was merged or published: this is the identical content already refused
against the newer version 1787673707-1257, resent unchanged.
The live version never changed (same version id on every read), and the payload is not "unchanged" relative to it — it contains ~9 edits. The refusal appears to compare the payload against the previously refused payload, not against the live version, so once a payload is rejected by the viewed-check it can never be accepted afterwards, even after the viewed-check is satisfied. After the third identical refusal the tool's own 3-strikes guard fires and instructs the model to stop calling Artifact for that target, leaving no path forward except force: true (which requires explicit user consent).
Environment
- Claude Code CLI (terminal), Linux, model Opus 5 (1M context)
- Artifact
4342961c-7237-450c-97d7-b58caca2aa93, owned by the session user, shared with the org - No
capabilitiesdeclared — this artifact does not self-publish, and no other session or viewer wrote to it during the episode - Live version fingerprint
1787673707-1257, identical on every read, before and after each refusal - Content: a ~60KB static HTML document, edited locally by targeted string replacements
Steps to reproduce
- Publish an artifact in an earlier session (context later cleared).
- In a new session,
Artifact action:"read"the URL. The result saves the full source to a local file and states: "this version counts as viewed only once you have Read every line of that file". - Read parts of that file (enough to work with), strip the injected
frame-runtimepreamble — i.e. take everything from<title>to</main>— apply edits to a local copy. Artifactpublish withfile_path= the edited copy andurl= the artifact URL.
Actual behavior
Attempt 1 (no favicon): favicon required to publish.
Attempt 2 (with favicon):
You hadn't viewed the live version of this artifact, so the publish was refused. Its full source
(60.5KB) is saved at <path>, and that version counts as viewed once you have Read every line of
that file: Read it in full and merge your edits onto it so no published content is lost, then
publish again from your own file [...]
I then did exactly that, in this order, all after the refusal:
Artifact action:"read"the URL again (returned the same version, same saved path)Readlines 1–171, 172–370, 371–505 of the saved file — i.e. every line of the 505-line file, including the 12KB minified runtime preamble on line 1- publish again with the same edited file
Attempts 3, 4 and 5, each after further full re-reads:
Publish refused — nothing was merged or published: this is the identical content already refused
against the newer version 1787673707-1257, resent unchanged. Merge your edits onto that version's
source [...] If your content genuinely already includes that version's changes, fetch the artifact's
URL again to confirm it (re-Reading a file an earlier refusal handed you does not count; [...])
Attempt 5 additionally triggered:
IMPORTANT: Artifact calls for this target have now been rejected 3 or more times in this session for
the same reason. Do not send the same call again [...]
Expected behavior
After fetching the artifact and reading its saved source in full, a publish carrying edits made on top of that exact version should succeed — especially when the live version never moved and nothing else wrote to the artifact.
Notes
- The "resent unchanged" wording is misleading: the payload differs substantially from the live version. What is unchanged is the payload relative to my own previous, refused attempt — which is inevitable, since the instructions say to merge edits onto that same version and republish.
- The two guards interact badly: the viewed-check rejects a payload, and the identical-payload check then permanently blocks the corrected retry of it. The only exits documented are
force: true(needs user confirmation, and per #89786 fails outright on self-publishing artifacts) or abandoning the update. - Related but distinct: #89786 reports the same "session hasn't viewed the latest version" guard being unsatisfiable from an agent session, but for an artifact with
capabilities: {artifact: {}}that a human had self-published. This report has no capabilities, no other writer, and a stable version id — so the guard is reachable in the plain single-writer case too.
Suggested fix directions
- Compare the submitted payload against the live version's content, not against previously refused payloads from the same session; a retry of a refused payload should be evaluated on its merits once the viewed-check passes.
- Make the viewed-state that
publishchecks the same state thataction:"read"+Readupdates, or state explicitly what does update it. - If a payload must be blocked as a duplicate, say what it is a duplicate of and how to make it acceptable, rather than repeating the merge instruction that produced it.