Skip to content

[WORKFLOW SDK BUG] error handling is messy when catching a duplicate workflow #874

@olitomlinson

Description

@olitomlinson

Expected Behavior

I would like to catch an explicit exception when a trying to schedule a workflow where the ID is already in use.

Something super simple and intuitive like this :

except WorkflowAlreadyExistsException as exception:
  logger.info(f"Workflow already exists for run_id {run_id}")

Actual Behavior

except Exception as schedule_error:
  if "already exists" in str(schedule_error):
      logger.info(f"Workflow already exists for run_id {run_id}")

Using string matching is a bad API for catching an exception.

I thought I might be able to catch the grpc.RpcError and then match on the .code() being grpc.StatusCode.ALREADY_EXISTS -- however this is always coming through as StatusCode.UNKNOWN - which could be a bug in its self.

try:
    workflow_client.schedule_new_workflow(
        workflow=tracker_workflow,
        instance_id=str(run_id),
        input={},
        reuse_id_policy=reuse_policy
    )
    logger.info(f"Scheduled tracker_workflow for run_id: {run_id}")
except grpc.RpcError as rpc_error:
    # Log full error details for debugging
    has_code = hasattr(rpc_error, 'code') and callable(rpc_error.code)
    has_details = hasattr(rpc_error, 'details') and callable(rpc_error.details)

    error_code = rpc_error.code() if has_code else 'NO_CODE_METHOD'
    error_details = rpc_error.details() if has_details else 'NO_DETAILS_METHOD'

    logger.info(f"⚠️ gRPC Error Details:")
    logger.info(f"  - Type: {type(rpc_error).__name__}")
    logger.info(f"  - Has code(): {has_code}")
    logger.info(f"  - Has details(): {has_details}")
    logger.info(f"  - Code: {error_code}")
    logger.info(f"  - Details: {error_details}")
    logger.info(f"  - String repr (first 200 chars): {str(rpc_error)[:200]}")

    # Check if it's ALREADY_EXISTS
    if has_code and error_code == grpc.StatusCode.ALREADY_EXISTS:
        logger.info(f"✅ Workflow already exists for run_id {run_id} (ALREADY_EXISTS) - continuing")
    else:
        logger.info(f"⚠️ Unexpected error code: {error_code} - continuing anyway")
== APP == 2025-12-30 22:51:49,747 - web_server - INFO - ⚠️ gRPC Error Details:
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - Type: _InactiveRpcError
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - Has code(): True
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - Has details(): True
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - Code: StatusCode.UNKNOWN
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - Details: failed to create orchestration instance: an active workflow with ID '8162906096' already exists
== APP == 2025-12-30 22:51:49,747 - web_server - INFO -   - String repr (first 200 chars): <_InactiveRpcError of RPC that terminated with:
== APP == 	status = StatusCode.UNKNOWN
== APP == 	details = "failed to create orchestration instance: an active workflow with ID '8162906096' already exists"
== APP == 	debug_error_s
== APP == 2025-12-30 22:51:49,747 - web_server - INFO - ⚠️ Unexpected error code: StatusCode.UNKNOWN - 

Release Note

RELEASE NOTE:

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions