{"record":{"id":"4de11d9e514872db","repo":"homebridge/homebridge","slug":"status-failure-4de11d","errorCode":"Status.Failure","errorMessage":"Failed to open window covering: ${message}","messagePattern":"Failed to open window covering: (.+?)","errorType":"exception","errorClass":"StatusResponseError","httpStatus":null,"severity":"error","filePath":"src/matter/behaviors/WindowCoveringBehavior.ts","lineNumber":110,"sourceCode":"      await super.upOrOpen()\n\n      // Sync state to cache - window covering opening\n      this.syncPositionStateToCache(\n        endpointId,\n        WindowCoveringStateProps.targetPositionLiftPercent100ths,\n        WindowCoveringStateProps.currentPositionLiftPercent100ths,\n      )\n    } catch (error) {\n      // If user handler already threw a StatusResponseError, propagate it as-is\n      // This sends a proper Matter protocol error response to the controller\n      if (MatterStatus.isMatterProtocolError(error)) {\n        throw error\n      }\n\n      // For other errors, wrap in appropriate StatusResponseError\n      // This prevents the endpoint from crashing and keeps the device online\n      const message = error instanceof Error ? error.message : String(error)\n      throw new StatusResponseError(`Failed to open window covering: ${message}`, Status.Failure)\n    }\n  }\n\n  override async downOrClose(): Promise<void> {\n    const endpointId = this.endpoint.id\n    const registry = this.getRegistry()\n\n    try {\n      // Execute user handler\n      await registry.executeHandler(endpointId, 'windowCovering', 'downOrClose')\n\n      // Only reached if handler succeeded - update Matter state\n      await super.downOrClose()\n\n      // Sync state to cache - window covering closing\n      this.syncPositionStateToCache(\n        endpointId,\n        WindowCoveringStateProps.targetPositionLiftPercent100ths,","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/homebridge/homebridge/blob/edf54930340d67cade23d01abd41b03cd9621e8b/src/matter/behaviors/WindowCoveringBehavior.ts#L92-L128","documentation":"StatusResponseError (Status.Failure) thrown by HomebridgeWindowCoveringServer.upOrOpen when the plugin's registered 'upOrOpen' handler throws a non-Matter error. The wrapper keeps the Matter endpoint alive and returns a protocol-level FAILURE to the controller, with the underlying error message appended. Genuine Matter protocol errors from the handler pass through untouched.","triggerScenarios":"A controller sends the WindowCovering UpOrOpen command and the plugin's upOrOpen handler rejects — e.g. the blind's motor API errors, times out, or the handler code throws. Also thrown if super.upOrOpen() (internal Matter state update) fails after a successful handler.","commonSituations":"Cloud-connected shades with expired tokens; local MQTT/HTTP bridge to the shade offline; plugin bug such as referencing an undefined accessory in the handler; race where the shade was removed while a command was in flight.","solutions":["Read the detail after 'Failed to open window covering:' in the log to find the real cause","Confirm the shade/blind device is online and controllable via the plugin's own app/API","Update or fix the plugin; in your own plugin, throw StatusResponseError from handlers for expected device failures so controllers get specific Matter statuses","Restart the bridge/plugin after resolving the device-side issue"],"exampleFix":"// before\nasync upOrOpen() { await shadeApi.open() }\n// after\nasync upOrOpen() {\n  if (!shadeApi.connected) throw new StatusResponseError('shade offline', Status.Failure)\n  await shadeApi.open()\n}","handlingStrategy":"try-catch","validationCode":"registry.registerHandler(endpointId, 'windowCovering', 'upOrOpen', async () => {\n  if (!shade.reachable) throw new StatusResponseError('shade unreachable', Status.Failure)\n})","typeGuard":"const isStatusResponseError = (e: unknown): e is StatusResponseError => e instanceof StatusResponseError","tryCatchPattern":"try { await sendUpOrOpen() }\ncatch (e) {\n  if (isStatusResponseError(e) && e.message.includes('Failed to open window covering:')) {\n    log.error('underlying:', e.message.split(': ').slice(1).join(': '))\n  }\n}","preventionTips":["Guard handler bodies with reachability checks and throw proper Matter statuses","Validate state transitions (e.g. not already open) before calling the device","Watch the log for the inner error message to fix the plugin, not just retry","Test handlers with the device offline to confirm graceful Status responses"],"tags":["matter","plugin-handler","window-covering","command-failed"],"backgroundTag":"matter-command-handler-failed","analyzedSha":"edf54930340d67cade23d01abd41b03cd9621e8b","analyzedAt":"2026-08-30T21:28:53.235Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}