Automation 7 min read Advanced

Why a successful Static Web Apps pipeline still returned 404

An incident note about a Synology NAS self-hosted agent where the build succeeded, the deploy task looked green, but Azure Static Web Apps still served an old route because of a workdir bind-mount mismatch.

Azure Pipelines Agent
4.273.0
Static Web Apps Client
stable
Docker
24.0.2
Server and infrastructure hardware representing a CI deployment path mismatch
자료 이미지: Photo by Eric Stoynov on Unsplash
On this page
  1. Symptom
  2. The Missing Mental Model
  3. Why the Pipeline Was Green
  4. Fix
  5. Verification
  6. Prevention

This incident looked contradictory at first.

The Azure DevOps pipeline succeeded. The article generation step succeeded. Astro generated the new route. The Static Web Apps deploy task did not fail. But the public URL still returned 404.

The root cause was not DNS, not CDN propagation, and not Astro routing. It was the work directory mount used by the self-hosted agent.

Symptom

The visible state was:

article generation: succeeded
Astro route generation: succeeded
Static Web Apps deploy task: succeeded
public article URL: 404

The build log included the expected route:

/kr/example-article-slug/index.html

But the public site did not serve it.

The Missing Mental Model

On a self-hosted agent, it is easy to think the deploy task uploads files directly from the agent process. In this case, that assumption was incomplete.

The Static Web Apps deployment task can start a helper container through Docker. That helper container sees host paths, not only the filesystem view inside the Azure Pipelines agent container.

The broken structure was conceptually this:

agent container: /azp/_work
NAS host:        /volume1/docker/hwmoon-azp-agent/_work
deploy helper:  tries to bind a host path

The agent container could build the latest dist directory. But the helper container did not necessarily see the same path. When those views diverge, the deploy step can upload stale artifacts while the pipeline still appears successful.

Why the Pipeline Was Green

The deploy helper had a directory to upload. From its perspective, the operation was valid. The problem was that the directory was not the fresh build output expected by the article generation step.

That creates a dangerous class of failure:

Build step sees new artifacts.
Deploy helper sees old artifacts.
Pipeline status is green.
Production still serves old content.

The pipeline is not lying. It is reporting that the upload task completed. The missing validation is whether the uploaded artifact was the intended artifact.

Fix

The fix was to make the agent work directory stable and visible in the same way to the agent and the helper container.

The operating rule became:

Use a host path that maps cleanly to the agent work directory expected by Azure Pipelines and Docker helper containers.

After correcting the bind mount, the deployment task uploaded the current build output and the public route began returning 200.

Verification

The recovery was not complete until the public URL was checked.

Useful checks:

npm run build
find dist -path '*example-article-slug/index.html'
curl -I https://news.hwmoon.com/kr/example-article-slug/

For this class of issue, the public curl check matters as much as the pipeline result.

Prevention

The prevention checklist is:

  • keep the self-hosted agent work directory stable
  • avoid hidden differences between container path and host path
  • clean checkout before deployment
  • verify generated routes in dist
  • verify production routes after deployment
  • treat a green deploy without route smoke checks as incomplete

This incident is a good reminder that CI/CD correctness is not only about commands. It is also about filesystem boundaries between the runner, the host, and helper containers.

Series

Publisher Infrastructure

Part 3 of 8. This series collects related build notes so the context is easier to follow later.

  1. 1. Building domain email with Azure DNS and Zoho Mail
  2. 2. Running an Azure DevOps self-hosted agent on Synology NAS
  3. 3. Why a successful Static Web Apps pipeline still returned 404
  4. 4. Using Azure Repos as the primary source and GitHub as a backup mirror
  5. 5. Automating NAS agent operations with Slack-based AIOps
  6. 6. Preventing another news.hwmoon.com article publishing outage
  7. 7. AdSense readiness operations for news.hwmoon.com
  8. 8. Fixing news.hwmoon.com deployment outages with self-healing agent healthchecks

Related