{"record":{"id":"a1543340bbaa78b4","repo":"semaphoreui/semaphore","slug":"executor-provider-is-not-initialised-check-runner","errorCode":null,"errorMessage":"executor provider is not initialised (check runner executor config)","messagePattern":"executor provider is not initialised \\(check runner executor config\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services/runners/executor_factory.go","lineNumber":61,"sourceCode":"// runner code free of nil-checks against the config tree.\nfunc resolveExecutorType(executorCfg *util.ExecutorConfig) util.ExecutorType {\n\tif executorCfg == nil || executorCfg.Type == \"\" {\n\t\treturn util.ExecutorTypeLocal\n\t}\n\treturn executorCfg.Type\n}\n\n// newExecutor wires per-task data through the Provider. Access keys are hydrated\n// here (not inside each Provider) so the behaviour is identical regardless of\n// strategy: ansible vault passwords, SSH keys, inventory keys, and the inventory\n// repo SSH key all land on the JobData before the Executor is built.\nfunc newExecutor(\n\tjobData JobData,\n\taccessKeys map[int]db.AccessKey,\n\tprovider tasks.ExecutorProvider,\n) (tasks.Executor, error) {\n\tif provider == nil {\n\t\treturn nil, fmt.Errorf(\"executor provider is not initialised (check runner executor config)\")\n\t}\n\n\thydrateJobAccessKeys(&jobData, accessKeys)\n\n\treturn provider.NewExecutor(\n\t\tjobData.Task,\n\t\tjobData.Template,\n\t\tjobData.Inventory,\n\t\tjobData.Repository,\n\t\tjobData.Environment,\n\t\tjobData.JWT,\n\t)\n}\n\n// hydrateJobAccessKeys decrypts/wires the access keys the server sent us into the\n// per-task data. Lives in the factory (not the Provider) so the behaviour is\n// identical across strategies — every executor sees the same shape of JobData.\nfunc hydrateJobAccessKeys(jobData *JobData, accessKeys map[int]db.AccessKey) {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/services/runners/executor_factory.go#L43-L79","documentation":"newExecutor was invoked with a nil ExecutorProvider, so no executor can be constructed for the job. The provider is created from the runner executor config; nil means the factory never produced one (e.g. unknown executor type or config omitted), so the guard fails fast with an actionable message instead of panicking on a nil pointer.","triggerScenarios":"checkNewJobs picks up a job and calls newExecutor while the JobPool's provider is nil — typically because newExecutorProvider returned (nil, err) at startup (unknown executor type, docker provider init failure) or the config tree was nil and nothing defaulted.","commonSituations":"Runner started with a misconfigured/invalid executor section so the provider was never initialized; provider construction failed at startup but the job loop kept running.","solutions":["Check runner startup logs for an error from newExecutorProvider and fix the executor configuration.","Set a valid executor.type in the runner config and restart the runner.","Ensure the runner fails fast at startup (or re-initializes the provider) instead of reaching the job loop with a nil provider."],"exampleFix":"// before\nprovider, _ := newExecutorProvider(cfg) // error ignored, provider nil\n// after\nprovider, err := newExecutorProvider(cfg)\nif err != nil {\n    return fmt.Errorf(\"init executor provider: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if pool.Provider() == nil {\n    return errors.New(\"executor provider not initialized; check runner executor config before accepting jobs\")\n}","typeGuard":"func providerReady(p tasks.ExecutorProvider) bool { return p != nil }","tryCatchPattern":"ex, err := newExecutor(jobData, keys, provider)\nif err != nil {\n    if strings.Contains(err.Error(), \"not initialised\") {\n        log.Error(\"executor provider missing; halting job processing for reconfiguration\")\n        return\n    }\n    return err\n}","preventionTips":["Fail runner startup hard when the executor provider cannot be built.","Log provider construction errors prominently at boot.","Test the runner config with a dry-run startup before production."],"tags":["runner","executor","nil-check","initialization"],"backgroundTag":"missing-required-config","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}