{"record":{"id":"bea865a271bbc52d","repo":"halo-dev/halo","slug":"unable-to-complete-the-request-because-the-theme-c","errorCode":null,"errorMessage":"Unable to complete the request because the theme configMapName is blank.","messagePattern":"Unable to complete the request because the theme configMapName is blank\\.","errorType":"http","errorClass":"ServerWebInputException","httpStatus":400,"severity":"error","filePath":"application/src/main/java/run/halo/app/theme/endpoint/ThemeEndpoint.java","lineNumber":290,"sourceCode":"                                .response(responseBuilder().implementation(Object.class)))\n                .build();\n    }\n\n    private Mono<ServerResponse> fetchThemeJsonConfig(ServerRequest request) {\n        return themeNameInPathVariableOrActivated(request)\n                .flatMap(themeName -> client.fetch(Theme.class, themeName))\n                .mapNotNull(theme -> theme.getSpec().getConfigMapName())\n                .flatMap(settingConfigService::fetchConfig)\n                .flatMap(json -> ServerResponse.ok().bodyValue(json));\n    }\n\n    private Mono<ServerResponse> updateThemeJsonConfig(ServerRequest request) {\n        final var themeName = request.pathVariable(\"name\");\n        return client.fetch(Theme.class, themeName)\n                .doOnNext(theme -> {\n                    String configMapName = theme.getSpec().getConfigMapName();\n                    if (StringUtils.isBlank(configMapName)) {\n                        throw new ServerWebInputException(\n                                \"Unable to complete the request because the theme configMapName is blank.\");\n                    }\n                })\n                .flatMap(theme -> {\n                    final var configMapName = theme.getSpec().getConfigMapName();\n                    return request.bodyToMono(ObjectNode.class)\n                            .switchIfEmpty(Mono.error(new ServerWebInputException(\"Required request body is missing\")))\n                            .flatMap(\n                                    configJsonData -> settingConfigService.upsertConfig(configMapName, configJsonData));\n                })\n                .then(ServerResponse.noContent().build());\n    }\n\n    private Mono<ServerResponse> invalidateCache(ServerRequest request) {\n        final var name = request.pathVariable(\"name\");\n        return client.get(Theme.class, name)\n                .flatMap(theme -> templateEngineManager.clearCache(name))\n                .then(ServerResponse.noContent().build());","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/theme/endpoint/ThemeEndpoint.java#L272-L308","documentation":"updateThemeJsonConfig() fetches the Theme resource by name and reads theme.spec.configMapName before upserting JSON config. If configMapName is blank (null, empty, or whitespace), there is no ConfigMap to write settings into, so a ServerWebInputException (HTTP 400) is thrown. A theme only has a configMapName when it ships a settings definition.","triggerScenarios":"Calling PUT /apis/api.console.halo.run/v1alpha1/themes/{name}/config (the theme JSON config update endpoint) for a Theme whose spec.configMapName was never set, e.g. a theme installed without a settings.yaml, or a manually-created Theme resource missing the configMapName/spec.settingName pair.","commonSituations":"Installing a theme that declares no settings form; a theme manifest whose spec omits configMapName; the ConfigMap was deleted out-of-band; editing a theme CR directly without the settings plumbing.","solutions":["Confirm the theme actually provides a settings form (theme.yaml spec.settingName and spec.configMapName). If not, there is nothing to configure; do not call the config update endpoint.","Reinstall or reload the theme so the configMapName/settings are provisioned.","If the theme is meant to have settings, fix its theme.yaml to include settingName/configMapName and reload.","Check the Theme CR in the cluster: kubectl get theme <name> -o yaml and verify spec.configMapName."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the Theme has a configMapName before calling the update endpoint:\nTheme theme = client.fetch(Theme.class, name).block();\nif (theme == null || StringUtils.isBlank(theme.getSpec().getConfigMapName())) {\n    throw new IllegalStateException(\"Theme '\" + name + \"' has no configMapName; cannot update config.\");\n}","typeGuard":null,"tryCatchPattern":"// In the handler, map the 400 to a user-friendly message:\n.onErrorResume(ServerWebInputException.class, e ->\n    ServerResponse.badRequest().bodyValue(Map.of(\n        \"message\", \"This theme has no settings form (configMapName is blank).\")))","preventionTips":["Only expose the config-update UI for themes whose spec.configMapName is non-blank.","Ensure themes declare settingName/configMapName in theme.yaml before install.","Reload themes after editing their manifest so settings plumbing is provisioned.","Unit-test the endpoint against a theme with no settings to confirm the 400 contract."],"tags":["theme","config","api","validation"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}