Skip to content

[DX] GAP-16: sdk.processes.invoke() silently ignores EntryPointPath, returns immediately, and has undocumented folder header #1508

@AlexBizon

Description

@AlexBizon

Summary

sdk.processes.invoke() has three separate issues that make it unusable for invoking specific entry points in multi-function packages: (1) EntryPointPath is silently ignored, (2) the method returns immediately after HTTP 201 without waiting for the job to complete, and (3) the correct folder context header is undocumented.

Root Cause

Part 1 — EntryPointPath silently ignored

The SDK's _invoke_spec builds {"ReleaseName": name, **(input_data or {})}. There is no slot for EntryPointPath. The **kwargs in invoke() extract only parent_span_id; all other kwargs are silently dropped.

# This has NO effect:
job = sdk.processes.invoke(
    name="invoice-tools",
    input_arguments={"blob_file_path": "invoices/inv001.pdf"},
    EntryPointPath="invoice_tools/extract.py:extract_invoice_data"  # silently ignored
)

The wrong (default) entry point runs. sdk.jobs.extract_output() returns None because the output schema doesn't match.

Part 2 — Fire-and-forget (no wait mechanism)

sdk.processes.invoke() returns after HTTP 201 (job queued), not after the job completes. Calling sdk.jobs.extract_output() on a still-running job returns None with no indication that the job hasn't finished.

Part 3 — Folder header undocumented

When calling the Orchestrator StartJobs API directly, the correct header is x-uipath-folderkey (not X-UIPATH-FolderPath). The Orchestrator runtime injects UIPATH_FOLDER_KEY as the env var. Using an empty X-UIPATH-FolderPath header produces HTTP 400 "A folder is required for this action" (errorCode 1101).

Current Workaround

Bypass the SDK entirely and poll manually:

folder_key = os.getenv("UIPATH_FOLDER_KEY", "")
headers = {
    "Authorization": f"Bearer {token}",
    "x-uipath-folderkey": folder_key,
}
payload = {"startInfo": {
    "ReleaseName": process_name,
    "EntryPointPath": "invoice_tools/extract.py:extract_invoice_data",
    "InputArguments": json.dumps(input_args),
}}
resp = httpx.post(
    f"{base_url}/orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.StartJobs",
    json=payload, headers=headers
)
job_key = resp.json()["value"][0]["Key"]

# Poll until terminal state
while True:
    job = sdk.jobs.retrieve(job_key)
    if job.state.lower() in {"successful", "faulted", "stopped", "abandoned"}:
        break
    time.sleep(2)

output_str = sdk.jobs.extract_output(job)
return json.loads(output_str)

Note: job.state is lowercase ("successful", "faulted") — not documented.

Suggested Fix

  1. Add entry_point: Optional[str] = None to sdk.processes.invoke() and include it in the StartJobs payload
  2. Add wait: bool = True (or poll_interval: float = 2.0) that polls until the job reaches a terminal state before returning
  3. Document that UIPATH_FOLDER_KEY (not UIPATH_FOLDER_PATH) is injected by the Orchestrator runtime, and that the correct header is x-uipath-folderkey
  4. Document the valid job.state values (lowercase strings) and which are terminal

Impact

  • Severity: High
  • Multi-function packages (the primary use case for uipath functions) cannot be invoked via the SDK
  • Three separate silent failures make this extremely hard to debug

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions