{"record":{"id":"e37cf801dbf09aab","repo":"grafana/k6","slug":"upload-archive-w","errorCode":null,"errorMessage":"upload archive: %w","messagePattern":"upload archive: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/provisioning/provision.go","lineNumber":93,"sourceCode":"\t\tarchiveBytes = buf.Bytes()\n\t}\n\n\tsleReq := StartLocalExecutionRequest{\n\t\tOptions:       params.Options,\n\t\tMaxVUs:        params.MaxVUs,\n\t\tTotalDuration: params.TotalDuration,\n\t\tArchiveSize:   archiveSize,\n\t}\n\n\tsleResp, err := c.StartLocalExecution(ctx, loadTestID, sleReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"start local execution: %w\", err)\n\t}\n\n\tswitch {\n\tcase params.Archive != nil && sleResp.ArchiveUploadURL != nil:\n\t\tif err := c.UploadArchive(ctx, *sleResp.ArchiveUploadURL, archiveBytes); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"upload archive: %w\", err)\n\t\t}\n\tcase params.Archive != nil && sleResp.ArchiveUploadURL == nil:\n\t\t// We had an archive to upload but the API returned no upload URL;\n\t\t// proceed without uploading rather than failing the run.\n\t\tc.logger.Warn(\"archive present but provisioning API returned no upload URL; skipping archive upload\")\n\t}\n\n\tif err := c.WaitForTestRunReady(ctx, sleResp.TestRunID, params.PollInterval); err != nil {\n\t\treturn nil, fmt.Errorf(\"wait for test run ready: %w\", err)\n\t}\n\n\treturn &ProvisionResult{\n\t\tTestRunID:             sleResp.TestRunID,\n\t\tTestRunDetailsPageURL: sleResp.TestRunDetailsPageURL,\n\t\tRuntimeConfig:         sleResp.RuntimeConfig,\n\t}, nil\n}\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/cloudapi/provisioning/provision.go#L75-L111","documentation":"ProvisionLocalExecution could not PUT the serialized archive bytes to the presigned upload URL returned by StartLocalExecution (sleResp.ArchiveUploadURL). The wrapped error is either an HTTP failure from the object store (S3/GCS) or a transport error; the presigned URL is short-lived and bound to the declared ArchiveSize.","triggerScenarios":"Presigned URL expired because too much time passed between StartLocalExecution and the upload, request signature mismatch when the uploaded body length differs from the declared ArchiveSize, network egress blocked to the object store domain, or the URL was already consumed.","commonSituations":"Slow links or large archives (>1 GB) exceeding URL validity, corporate firewalls allowing the API host but blocking *.amazonaws.com, or code that mutates/re-serializes the archive between computing archiveBytes and uploading it.","solutions":["Retry provisioning end-to-end to get a fresh presigned URL — do not cache or reuse ArchiveUploadURL","Make sure the exact same archiveBytes buffer produced during serialization is what gets uploaded (no second Write)","Allow egress to the object-store domain reported in the error (often S3) in proxy/firewall rules","Compress or shrink the archive (drop unused data files) if uploads routinely outlive the URL lifetime"],"exampleFix":"// before\narchiveBytes = maybeRewritten // re-serialized or modified after size was computed\nerr := client.UploadArchive(ctx, *sleResp.ArchiveUploadURL, archiveBytes)\n\n// after\n// upload the identical buffer whose length was declared\nerr := client.UploadArchive(ctx, *sleResp.ArchiveUploadURL, archiveBytes)","handlingStrategy":"retry","validationCode":"// guard the invariant: declared size must equal uploaded bytes\nif sleResp.ArchiveUploadURL != nil && int64(len(archiveBytes)) != sleReq.ArchiveSize {\n    return nil, fmt.Errorf(\"archive size drift: declared %d, have %d\", sleReq.ArchiveSize, len(archiveBytes))\n}","typeGuard":null,"tryCatchPattern":"err := c.UploadArchive(ctx, *sleResp.ArchiveUploadURL, archiveBytes)\nif err != nil {\n    if isTransientOrExpired(err) {\n        // re-run provisioning to obtain a fresh presigned URL; do not reuse it\n        return nil, fmt.Errorf(\"upload archive (re-provision for new URL): %w\", err)\n    }\n    return nil, fmt.Errorf(\"upload archive: %w\", err)\n}","preventionTips":["Upload immediately after StartLocalExecution; presigned URLs are short-lived","Freeze the archive bytes buffer after computing its length and upload that exact slice","Pre-verify firewall egress to the object-store domain, not just the API host"],"tags":["upload","presigned-url","s3","provisioning","network"],"backgroundTag":"presigned-url-upload-failed","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}