Repository navigation
Survey.generate_report() — add job timeout and cancel support #2531
Description
Is your feature request related to a problem? Please describe.
![]()
In the example above I Had to cancel it manually, after 2h.
Survey.generate_report() submits a Feature Report job and polls forever with no timeout (internal loop sleeps while esriJobExecuting with no deadline). In batch/ETL PDF generation, a stuck job hangs the process indefinitely. The method also does not return jobId, so callers cannot cancel a hung job via the Survey123 cancel endpoint.
We had to bypass generate_report() and reimplement submit + poll against the same REST API just to add a timeout and a real cancel.
from arcgis.gis import GIS
from arcgis.apps.survey123 import SurveyManager
gis = GIS(url, username, password)
survey = SurveyManager(gis).get("<survey_item_id>")
template = gis.content.get("<report_template_item_id>")
# Can hang forever if the job never leaves esriJobExecuting
# (no timeout kwarg; no jobId returned to cancel)
result = survey.generate_report(
report_template=template,
where="OBJECTID=1",
utc_offset="+00:00",
output_format="pdf",
)Describe the solution you'd like
Add optional timeout / cancel controls on Survey.generate_report() (or SurveyManager):
job_timeout(seconds) — stop polling after N seconds and raise a clear error (e.g.TimeoutError).cancel_on_timeout— callPOST .../api/featureReport/jobs/{jobId}/cancelso the remote job does not keep running after the client gives up.- Optionally expose
jobId(or a job handle) so callers can cancel/track jobs themselves.
Example:
result = survey.generate_report(
report_template=template,
where="OBJECTID=1",
output_format="pdf",
job_timeout=90, # NEW
cancel_on_timeout=True, # NEW
)The cancel endpoint already works in practice (POST .../api/featureReport/jobs/{jobId}/cancel → esriJobStatusCancelled).
Describe alternatives you've considered
- Reimplement submit + poll ourselves (current workaround) — duplicate
_survey.pylogic against/createReport/submitJob,/jobs/{id}/status, and/cancel. Works, but fragile if the private API changes. - External process/watchdog timeout — kills the Python process but does not cancel the remote job; wastes credits and leaves orphan jobs.
- Thread + interrupt — still no access to
jobId, so cancel is impossible.
Additional context
- Affected API:
arcgis.apps.survey123.Survey.generate_report - Use case: automated batch PDF Feature Reports in an ETL pipeline (ArcGIS Enterprise / AGOL)
- Related endpoints already used successfully outside the Python API:
POST /api/featureReport/createReport/submitJobGET /api/featureReport/jobs/{jobId}/statusPOST /api/featureReport/jobs/{jobId}/cancel
Activity
kyroskoh commentedon Aug 13, 2026
Temporary workaround for 2.4.3 users
This public repo is docs/samples only, so a library source PR cannot land here. Confirmed in
arcgis2.4.3:Survey.generate_report→_check_statuspolls forever while status isesriJobSubmitted/esriJobExecuting(no deadline, no cancel, nojobIdexposed).Full usage, limits, unit tests, and removal steps:
misc/tools/issue_2531/README.mdon branchfix/issue-2531-survey-generate-report-timeout.Monkey-patch module:
fix_survey_generate_report_timeout_2531.pyOr copy the file next to your script:
What it adds
job_timeout— client-side poll deadline; raisesTimeoutErrorwithjobIdcancel_on_timeout— best-effort cancel viaPOST /api/featureReport/jobs/{jobId}/cancelsurvey.last_report_job_id+cancel_report_job(...)so callers can cancel/track without reimplementing submit/pollMock unit tests (no live portal calls):
Removing the patch when Esri ships a fix
See When Esri releases a fix in the README. Short version:
arcgisrelease that includes the#2531fix (check the release notes).apply(),job_timeout/cancel_on_timeoutunless upstream added the same names).apply():misc/tools/issue_2531/.