Hi everyone
So we are using a custom theme (which imports from the light theme) and has a custom set of variables in variables.css.
In Windows we simply drop files in the relevant folder, but when using docker containers we either docker cp in and out or mount the themes folder to something on the host.
In an effort to simplify this action we have created a few views to CRUD custom themes which works fine with the GET calls until we tried to update the variables.css file via a PUT call as per the API doc:
API key has the Write Security Level and so does the Gateway Write Permissions setting.
The response (which, oddly enough reported success:true in 8.3.4 but now at least says success:false in 8.3.6) is as follows:
{
"success": false,
"changes": [],
"problem": {
"message": "I/O error during prepare: /usr/local/bin/ignition/data/config/resources/core/com.inductiveautomation.perspective/themes/standard-dark/variables.css.tmp",
"stacktrace": [
"com.inductiveautomation.ignition.common.resourcecollection.PushException: I/O error during prepare: /usr/local/bin/ignition/data/config/resources/core/com.inductiveautomation.perspective/themes/standard-dark/variables.css.tmp",
"\tat com.inductiveautomation.ignition.gateway.resourcecollection.ChangeOperationValidationHandler$AtomicPushValidationHandler.throwIfInvalid(ChangeOperationValidationHandler.java:61)",
"\tat com.inductiveautomation.ignition.gateway.resourcecollection.ResourceCollectionManagerImpl.push(ResourceCollectionManagerImpl.java:1129)",
"\tat com.inductiveautomation.ignition.gateway.config.ConfigurationManagerImpl.push(ConfigurationManagerImpl.java:409)",
"\tat com.inductiveautomation.ignition.gateway.config.actions.DefaultResourceActions$ModifyImpl.modify(DefaultResourceActions.java:185)",
"\tat com.inductiveautomation.ignition.gateway.config.actions.DefaultResourceActions$Modify.modify(DefaultResourceActions.java:140)",
"\tat com.inductiveautomation.ignition.gateway.config.routes.ResourceTypeRoutes.modifyDatafile(ResourceTypeRoutes.java:732)",
"\tat com.inductiveautomation.ignition.gateway.config.routes.NamedTypeRoutes.replaceDataFileHandler(NamedTypeRoutes.java:736)",
"\tat com.inductiveautomation.ignition.gateway.config.routes.NamedTypeRoutes.lambda$mountReplaceDataFileRoute$19(NamedTypeRoutes.java:601)",
"\tat com.inductiveautomation.ignition.gateway.dataroutes.Route.service(Route.java:355)",
"\tat com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupImpl.service(RouteGroupImpl.java:117)",
"\tat com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupCollectionServlet.serviceInternal(RouteGroupCollectionServlet.java:151)",
"\tat com.inductiveautomation.ignition.gateway.dataroutes.AbstractRouteGroupServlet.service(AbstractRouteGroupServlet.java:40)",
"\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1385)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:751)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1622)",
"\tat com.inductiveautomation.catapult.filters.GatewayFilter.doFilter(GatewayFilter.java:119)",
"\tat jakarta.servlet.http.HttpFilter.doFilter(HttpFilter.java:97)",
"\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1594)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1555)",
"\tat org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:823)",
"\tat org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:440)",
"\tat org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:470)",
"\tat org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:575)",
"\tat org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:717)",
"\tat org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1071)",
"\tat org.eclipse.jetty.rewrite.handler.RewriteHandler$LastRuleHandler.handle(RewriteHandler.java:159)",
"\tat org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)",
"\tat org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)",
"\tat org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)",
"\tat org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)",
"\tat org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)",
"\tat org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)",
"\tat org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)",
"\tat org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)",
"\tat org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)",
"\tat org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:143)",
"\tat org.eclipse.jetty.server.Handler$Sequence.handle(Handler.java:805)",
"\tat org.eclipse.jetty.server.Handler$Sequence.handle(Handler.java:805)",
"\tat org.eclipse.jetty.server.Server.handle(Server.java:182)",
"\tat org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:677)",
"\tat org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:416)",
"\tat org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)",
"\tat org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)",
"\tat org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)",
"\tat org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)",
"\tat org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)",
"\tat org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)",
"\tat org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)",
"\tat org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)",
"\tat org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:981)",
"\tat org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1211)",
"\tat org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1166)",
"\tat java.base/java.lang.Thread.run(Unknown Source)"
]
}
}
Is this an issue with write permissions on the container?
Compose:
# Docker Compose Example for inductiveautomation/ignition
# Compose Spec: https://github.com/compose-spec/compose-spec/blob/master/spec.md
services:
# Ignition Gateway
gateway:
image: inductiveautomation/ignition:8.3.6
ports:
- 9088:8088
- 9043:8043
- 9060:8060
volumes:
- gw-data:/usr/local/bin/ignition/data
- /share:/usr/local/bin/backups
# env_file: ignition.env # optionally specify variables in a file, or using `environment:` below
environment:
- ACCEPT_IGNITION_EULA=Y
- GATEWAY_ADMIN_USERNAME=
- GATEWAY_ADMIN_PASSWORD=
- IGNITION_EDITION=standard
- TZ=Africa/Johannesburg # see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
command: >
-n Ignition -m 4096 -- wrapper.java.initmemory=512
-Dignition.allowunsignedmodules=true
volumes:
gw-data: null
networks: {}
Gateway log errors:
ERROR
ResourceTypePartition
19May2026 16:58:26
Aborted change operations for [ModifyResourceOperation{resourceId=ResourceId{resourcePath=com.inductiveautomation.perspective/themes/standard-dark, collectionName=core}}] in collection core
ERROR
ResourceTypePartition
19May2026 16:58:26
I/O error during prepare for ModifyResourceOperation{resourceId=ResourceId{resourcePath=com.inductiveautomation.perspective/themes/standard-dark, collectionName=core}} in collection core