{"record":{"id":"9a3282f8260a84ab","repo":"microsoft/aspire","slug":"java-application-resource-name-cannot-be-published-because-9a3282","errorCode":null,"errorMessage":"Java application '{resource.Name}' cannot be published because its working directory was changed to '{resource.WorkingDirectory}' after the container build context was set to '{appDirectory}'. Pass the directory to AddJavaApp instead of calling WithWorkingDirectory afterwards.","messagePattern":"Java application '(.+?)' cannot be published because its working directory was changed to '(.+?)' after the container build context was set to '(.+?)'\\. Pass the directory to AddJavaApp instead of calling WithWorkingDirectory afterwards\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Java/JavaHostingExtensions.cs","lineNumber":135,"sourceCode":"                if (File.Exists(Path.Combine(appDirectory, \"Dockerfile\")))\n                {\n                    resource.Annotations.Add(new JavaAuthoredDockerfileAnnotation());\n                    return;\n                }\n\n                containerBuilder.WithDockerfileBuilder(\n                    appDirectory,\n                    ctx =>\n                    {\n                        // The build context was fixed when PublishAsDockerFile ran, which is during\n                        // AddJavaApp, and DockerfileBuildAnnotation.ContextPath cannot be changed\n                        // afterwards. A later WithWorkingDirectory therefore moves where the application\n                        // runs without moving what is uploaded to the daemon, and the image would be built\n                        // from the original directory. Saying so is far better than producing an image\n                        // whose sources come from somewhere the author no longer points at.\n                        if (!ArePathsEquivalent(resource.WorkingDirectory, appDirectory))\n                        {\n                            throw new DistributedApplicationException(\n                                $\"Java application '{resource.Name}' cannot be published because its working \" +\n                                $\"directory was changed to '{resource.WorkingDirectory}' after the container \" +\n                                $\"build context was set to '{appDirectory}'. Pass the directory to \" +\n                                \"AddJavaApp instead of calling WithWorkingDirectory afterwards.\");\n                        }\n\n                        JavaDockerfileGenerator.Write(resource, appDirectory, ctx);\n                    });\n            });\n\n        // The generated image copies files out of each container files source, so those sources have to be\n        // built first. PublishAsDockerFile removes the Java resource from the model, but the container it\n        // substitutes shares this annotation collection, so the callback still runs; the step lookup matches\n        // on resource name and therefore finds the substituted container's build steps.\n        resourceBuilder.WithPipelineConfiguration(context =>\n        {\n            if (resource.TryGetAnnotationsOfType<ContainerFilesDestinationAnnotation>(out var containerFilesAnnotations))\n            {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Java/JavaHostingExtensions.cs#L117-L153","documentation":"AddJavaApp captures the working directory as the Docker build context at creation time. Calling WithWorkingDirectory afterwards changes where the app runs without changing the build context, so the published image would be built from stale sources. Aspire detects the mismatch at publish time and throws, telling you to pass the directory to AddJavaApp instead.","triggerScenarios":"Calling builder.AddJavaApp(name, appDirectory) and later resource.WithWorkingDirectory(otherDir) where otherDir differs from appDirectory, then publishing.","commonSituations":"Refactoring run behavior to a different output directory; copying patterns from other resource types where WithWorkingDirectory is common; assuming WithWorkingDirectory also moves the build context.","solutions":["Remove the WithWorkingDirectory call and pass the intended directory directly to AddJavaApp.","If run directory and build context must genuinely differ, restructure so AddJavaApp's appDirectory is the directory you want for both.","Keep a single source of truth for the app directory in the AddJavaApp call."],"exampleFix":"// before\nvar api = builder.AddJavaApp(\"api\", \"src/Api\");\napi.WithWorkingDirectory(\"src/Api/bin\");\n// after\nvar api = builder.AddJavaApp(\"api\", \"src/Api\");","handlingStrategy":"validation","validationCode":"var appDir = \"src/Api\";\nvar runDir = \"src/Api\"; // intended working directory\nif (!string.Equals(Path.GetFullPath(appDir), Path.GetFullPath(runDir), StringComparison.OrdinalIgnoreCase))\n    throw new Exception(\"Pass the working directory to AddJavaApp, not WithWorkingDirectory\");","typeGuard":null,"tryCatchPattern":"try { /* publish */ }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"WithWorkingDirectory afterwards\"))\n{ /* move the directory into AddJavaApp and remove the later call */ }","preventionTips":["Treat AddJavaApp's directory as the single source of truth","Avoid WithWorkingDirectory on Java app resources","Review resource chains for post-hoc directory mutations before publishing"],"tags":["java","working-directory","publish","build-context"],"backgroundTag":"conflicting-config-options","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}