I operate PhotoCraft AI, an online image editor with PSD editing, conversational
AI image editing, and AI image generation. Alongside the product, I am building a
small browser workflow for preparing product submissions, with a human reviewing
the final fields before anything is published.
This article covers an early local test of that workflow: how to handle a browser
command that reports a timeout after its action has already taken effect. It is
not a claim about PhotoCraft's image-editing internals or a completed multi-platform
submission system.
The observation
During a local browser-automation test on macOS, a CLI click returned a timeout.
The shell process still returned exit code 0. Inspection of the resulting browser
state showed that the click's intended effect had occurred.
This was a harmless local fixture: the button set a test cookie. It was not a
payment, an email, or a public post. But it exposed the problem with treating every
timeout as permission to retry a side effect.
A timeout tells us the client did not observe the expected completion. It does
not establish that the remote system did nothing.
The example uses the name and URL of PhotoCraft AI,
which I operate, as test data. All browser actions described here used a local
HTML fixture; they did not submit an entry to a public website.
Keep the boundary before the external action
For a small, human-assisted workflow, the important state transition is:
awaiting_confirmation → submitting → observed result
↘ unknown
Commit submitting before clicking the final button. If the process crashes,
the next run sees an unfinished external attempt rather than a fresh task.
Do not automatically reset that state to the queue.
The local application uses a database uniqueness constraint for one product at
one opportunity:
UNIQUE(site_id, channel_id)
That constraint prevents duplicate local records. It does not make a database
transaction atomic with a third-party website. Existing website records and
ambiguous outcomes still need read-only reconciliation.
Check the command output as well as the exit code
For the CLI version used in this test, an execution wrapper checks both:
if proc.returncode or "### Error" in result:
raise WorkflowError(
"Browser command failed; inspect the page before retrying any external action"
)
Here result is the captured CLI output. The wrapper writes output to an
unlinked temporary file before reading it, avoiding a dependency on a detached
daemon closing an inherited output pipe. A fresh browser launch through this
wrapper was tested after changing the capture strategy.
The textual marker is version-specific. Pin the tool, inspect its actual help
and output, and test this behavior. The wrapper detects a command failure; it
cannot decide whether the website accepted an action. That decision belongs to
the workflow's reconciliation step.
Persisting a browser is a separate concern
Another local test closed and reopened Chrome with the same persistent Profile.
localStorage survived, but the test cookie did not. The cause has not been isolated.
Explicit state export, reopening, state import and reload restored both markers
in this environment.
This is evidence for a tested recovery path, not a claim that Profile persistence
is generally broken or that an exported state file covers every authentication
method. OAuth, sessionStorage, IndexedDB and a site's own expiration policy need
their own tests. Authentication exports also need to be treated as credentials.
Tests worth keeping
- Reimporting the same opportunity must not reset a submitted record.
- A process restart must leave
submittingblocked from automatic retries. - A timeout must not be translated into a proven, retryable rejection.
- A paid or explicitly restricted opportunity must be rejected before execution.
- A pending-review receipt must not become a failure because no public URL exists.
- A public page containing the product name must not count as a verified link unless its actual anchor points to the intended target.
For human handoff, a local fixture let the user complete a browser step directly.
The agent then read a fresh snapshot and continued. This tests cooperation without
using a real account, a challenge bypass, or a public side effect.
The practical limit is that these checks reduce accidental repetition; they do
not promise exactly-once delivery to a third-party form.
Disclosure: AI assisted in drafting this article using the implementation
and local test observations described above.
Top comments (0)