{"record":{"id":"fd945a0a9cb42690","repo":"OpenHands/OpenHands","slug":"failed-to-disable-the-imported-automation-and-clea","errorCode":null,"errorMessage":"Failed to disable the imported automation and clean it up.","messagePattern":"Failed to disable the imported automation and clean it up\\.","errorType":"exception","errorClass":"AggregateError","httpStatus":null,"severity":"error","filePath":"src/api/automation-service/automation-service.api.ts","lineNumber":371,"sourceCode":"      );\n      return data;\n    } catch (updateError) {\n      try {\n        if (active.backend.kind === \"cloud\") {\n          await callCloudProxy<unknown>({\n            backend: active.backend,\n            method: \"DELETE\",\n            path: updatePath,\n            headers: await buildPinnedCloudHeaders(active),\n          });\n        } else {\n          await localAutomationAxios.delete(\n            updatePath,\n            await buildPinnedLocalConfig(active.backend),\n          );\n        }\n      } catch (cleanupError) {\n        throw new AggregateError(\n          [updateError, cleanupError],\n          \"Failed to disable the imported automation and clean it up.\",\n        );\n      }\n      throw updateError;\n    }\n  }\n\n  static async updateAutomation(\n    id: string,\n    body: Partial<Automation>,\n  ): Promise<Automation> {\n    const active = getActiveBackend().backend;\n    const path = `${AUTOMATION_BASE_PATH}${getAutomationIdEndpoint(\"detail\", id)}`;\n\n    if (active.kind === \"cloud\") {\n      return callCloudProxy<Automation>({\n        backend: active,","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/OpenHands/OpenHands/blob/500b4c533e9393e44cb92894bcbb18438ef473b6/src/api/automation-service/automation-service.api.ts#L353-L389","documentation":"AggregateError thrown during createAutomation when the initial PATCH (to set the real trigger and disable the automation) fails AND the subsequent DELETE cleanup also fails. The AggregateError contains both errors: [updateError, cleanupError]. This represents a partially-created automation that could not be cleaned up — the automation record exists in a pending/placeholder state on the server.","triggerScenarios":"createAutomation does a two-step: POST to create with a placeholder trigger, then PATCH to set the real trigger and disable it. If the PATCH fails (network error, server error, validation error), it tries DELETE to clean up. If the DELETE also fails, this AggregateError is thrown with both errors. The automation record is left orphaned on the server.","commonSituations":"Agent-server or automation backend restarts between the POST and PATCH; the automation backend has a schema mismatch that accepts the POST but rejects the PATCH; network instability causes both the PATCH and DELETE to time out; the automation backend process crashed after the POST but before the PATCH.","solutions":["Check the AggregateError.errors array — the first error is the PATCH failure, the second is the DELETE failure — to diagnose the root cause.","Manually clean up the orphaned automation record via DELETE /api/automation/v1/automations/{id} using the created automation's ID (visible in server logs).","Restart the automation backend (uvx process) if it crashed, then retry the import.","Verify the automation backend version matches the SDK version expected by Canvas (npm run check-sdk-version-sync)."],"exampleFix":"// handling the aggregate error\ntry {\n  await AutomationService.createAutomation(spec);\n} catch (error) {\n  if (error instanceof AggregateError) {\n    console.error('PATCH failed:', error.errors[0]);\n    console.error('Cleanup DELETE also failed:', error.errors[1]);\n    // manually clean up the orphaned record if possible\n  }\n  throw error;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isAggregateError(e: unknown): e is AggregateError {\n  return typeof AggregateError !== 'undefined' && e instanceof AggregateError;\n}","tryCatchPattern":"try {\n  await AutomationService.createAutomation(spec);\n} catch (error) {\n  if (error instanceof AggregateError) {\n    const [updateErr, cleanupErr] = error.errors;\n    console.error('Import failed:', updateErr);\n    console.error('Cleanup also failed — orphaned record may exist:', cleanupErr);\n    // Attempt manual cleanup if the created ID is known\n  }\n  throw error;\n}","preventionTips":["Check automation backend health before importing — if it's unhealthy, both PATCH and DELETE will fail.","After an AggregateError, list automations to find and manually delete orphaned placeholder records.","Keep the automation backend version in sync with the agent-server SDK version (npm run check-sdk-version-sync)."],"tags":["automation","compound-error","cleanup","partial-failure"],"backgroundTag":null,"analyzedSha":"500b4c533e9393e44cb92894bcbb18438ef473b6","analyzedAt":"2026-08-12T10:07:46.034Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}