floci-io/floci · critical · IllegalStateException

Boot hook execution failed

Error message

Boot hook execution failed

What it means

Thrown by EmulatorLifecycle.onStart when running BOOT-phase initialization hooks fails with an IOException — e.g. a hook script cannot be read, executed, or its process fails. BOOT hooks run before service initialization (AWS APIs are not usable yet), so any hook failure aborts Quarkus startup with IllegalStateException; the original IOException is chained.

Source

Thrown at src/main/java/io/github/hectorvent/floci/lifecycle/EmulatorLifecycle.java:169

        this.containerTeardowns = containerTeardowns;
        this.persistentPathValidator = persistentPathValidator;
    }

    void onStart(@Observes StartupEvent ignored) {
        LOG.infof("=== AWS Local Emulator %s Starting ===", appVersion.orElse(""));
        LOG.infof("Endpoint:  http://0.0.0.0:%d", config.port());
        LOG.infof("Region:    %s  Account: %s", config.defaultRegion(), config.defaultAccountId());
        LOG.infov("Storage:   {0}  Path: {1}", config.storage().mode(), config.storage().persistentPath());
        LOG.infov("TLS:       {0}", config.tls().enabled() ? "enabled (HTTPS + HTTP dual mode)" : "disabled (HTTP only)");

        // BOOT hooks run before service initialization — scripts cannot use AWS APIs yet.
        try {
            initializationHooksRunner.run(InitializationHook.BOOT);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException("Boot hook execution interrupted", e);
        } catch (IOException e) {
            throw new IllegalStateException("Boot hook execution failed", e);
        }
        initLifecycleState.markBootCompleted();

        persistentPathValidator.validateAtBoot();

        serviceRegistry.logEnabledServices();
        storageFactory.loadAll();
        schemaCreationWorker.recoverOrphans();
        schemaCreationWorker.rehydrateSchemas();

        sqsPoller.startPersistedPollers();
        kinesisPoller.startPersistedPollers();
        dynamodbStreamsPoller.startPersistedPollers();
        pipesService.startPersistedPollers();
        rdsService.restorePersistedRuntime();
        if (config.services().elbv2().enabled()) {
            elbV2Service.restorePersistedRuntime();
        }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Inspect the chained IOException / preceding logs to identify the failing hook
  2. Verify the script path exists inside the container and is executable (chmod +x), with a valid shebang
  3. Fix or remove the hook from the BOOT hook configuration, then restart
  4. Ensure dependencies used by the hook exist in the image and that it does not call AWS APIs (none are up at BOOT phase)

Example fix

# before
floci.init-hooks.boot[0].script = /opt/hooks/init.sh  # not executable

# after
RUN chmod +x /opt/hooks/init.sh  # in Dockerfile
# or locally: chmod +x hooks/init.sh
Defensive patterns

Strategy: validation

Validate before calling

boolean bootHookRunnable(String scriptPath) {
    Path p = Path.of(scriptPath);
    return Files.isRegularFile(p) && Files.isReadable(p) && Files.isExecutable(p);
}

Try / catch

try {
    app.run(args);
} catch (IllegalStateException e) {
    if (e.getMessage().equals("Boot hook execution failed")) { fixHookFromCause((IOException) e.getCause()); }
}

Prevention

When it happens

Trigger: Configured BOOT hook script missing, not executable, bad interpreter path, or exiting with an error; unreachable path inside the container. The hooks runner throws IOException before services like storage loadAll or poller startup happen.

Common situations: Hook script not mounted into the Docker image or wrong path in config; lost execute bit (git on Windows, COPY without chmod); scripts referencing tools absent from the image; migrating configs between environments with different filesystem layouts.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/b82c2f7ce0ec37b6. Report an issue: GitHub.