halo-dev/halo · error · IllegalStateException

Publishing wait timeout.

Error message

Publishing wait timeout.

What it means

Thrown as an IllegalStateException (HTTP 500) by SinglePageEndpoint.publishSinglePage during a synchronous publish. After setting spec.releaseSnapshot and updating, the endpoint re-fetches the page and waits for the reconciler to populate the LAST_RELEASED_SNAPSHOT annotation to match the requested release snapshot. It retries 10 times at 100ms intervals; if the annotation still mismatches, doOnError rethrows 'Publishing wait timeout.'

Source

Thrown at application/src/main/java/run/halo/app/core/endpoint/console/SinglePageEndpoint.java:348

                        return Mono.just(post);
                    }
                    return client.fetch(SinglePage.class, name)
                            .flatMap(latest -> {
                                var latestReleasedSnapshotName =
                                        MetadataUtil.nullSafeAnnotations(latest).get(Post.LAST_RELEASED_SNAPSHOT_ANNO);
                                if (!StringUtils.equals(
                                        latestReleasedSnapshotName,
                                        latest.getSpec().getReleaseSnapshot())) {
                                    return Mono.error(new IllegalStateException(
                                            "SinglePage publishing status is not as expected"));
                                }
                                return Mono.just(latest);
                            })
                            .retryWhen(Retry.fixedDelay(10, Duration.ofMillis(100))
                                    .filter(IllegalStateException.class::isInstance))
                            .doOnError(IllegalStateException.class, err -> {
                                log.error("Failed to publish single page [{}]", name, err);
                                throw new IllegalStateException("Publishing wait timeout.");
                            });
                })
                .flatMap(page -> ServerResponse.ok().bodyValue(page));
    }

    Mono<ServerResponse> listSinglePage(ServerRequest request) {
        var listRequest = new SinglePageQuery(request);
        return singlePageService
                .list(listRequest)
                .flatMap(listedPages -> ServerResponse.ok().bodyValue(listedPages));
    }
}

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Retry the publish request after a few seconds once the reconciler has had time to run.
  2. Publish with ?async=true to skip the wait-for-reconcile step and return immediately after the spec update.
  3. Inspect server logs for the logged 'Failed to publish single page [{name}]' and any reconciler errors, then fix the underlying reconcile failure.
  4. Check extension reconcile health and DB latency; restart the pod if the reconciler is wedged.

Example fix

// before: synchronous publish that times out
//   POST /apis/.../singlepages/{name}/publish
// after: fire-and-forget async publish
//   POST /apis/.../singlepages/{name}/publish?async=true
Defensive patterns

Strategy: retry

Validate before calling

// prefer async publish to avoid the synchronous reconcile wait
boolean async = true; // set ?async=true on the publish request

Try / catch

// reactive: retry publish a couple of times with backoff, fall back to async
client.postPublish(name)
    .retryWhen(Retry.backoff(3, Duration.ofSeconds(2))
        .filter(t -> t instanceof IllegalStateException))
    .onErrorResume(IllegalStateException.class,
        e -> client.postPublishAsync(name));

Prevention

When it happens

Trigger: POST /apis/api.console.halo.run/v1alpha1/singlepages/{name}/publish WITHOUT ?async=true when the SinglePage reconciler is slow, stalled, or erroring so that metadata.annotations['plugin.halo.run/last-released-snapshot'] never catches up to spec.releaseSnapshot within ~1 second.

Common situations: Reconciler thread pool saturated under load; the snapshot/reconciler controller threw and stopped updating the page; database latency pushes reconcile past the 1s budget; a custom plugin hook blocks the reconcile; deploying on a resource-constrained node where reconcile is slow.

Understand the failure class

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/1dfb28fda51599df. Report an issue: GitHub.