Skip to content

k6 cloud run (non---local-execution) rejects archives containing open()-bundled data files as "not UTF-8 javascript text" #6295

Description

@acv-yli

Brief summary

A test script that loads a JSON data file via open() inside a SharedArray fails to upload when run via k6 cloud run <archive>.tar (real cloud/private-load-zone execution), with:

level=error msg="uploading test: (400/validation_error) Uploaded content must be a javascript text encoded in UTF-8."

The identical test succeeds via k6 cloud run --local-execution <archive>.tar, and a script with no open()/bundled data files succeeds via the same non-local path that fails for the open() version. So the failure is specific to the combination of (a) the non-local upload path and (b) an archive whose "files" section is non-empty.

Looking at the client source, cmdCloud.run() (internal/cmd/cloud.go) builds the full archive via test.makeArchive() and uploads it through client.UploadTest()createTest() (internal/cloudapi/v6/api.go), which sends the entire archive stream through a parameter named Script(archiveReader(arc)). That suggests the server-side validation behind that field expects plain JS source text, and chokes when the archive's bundled non-JS open()'d files are included. --local-execution doesn't hit this because it goes through a different, newer provisioning-API + presigned-S3-upload path instead.

Environment

k6 version

latest tag as of 2026-08-14 (pulled via an internal registry mirror of grafana/k6:latest; exact pinned version unknown at filing time — happy to provide k6 version output if that's not sufficient)

OS

Linux, running inside the official grafana/k6 Docker image via docker run, itself on a Kubernetes-hosted CI agent

Docker version and image (if applicable)

grafana/k6:latest (via docker run --entrypoint=/bin/sh)

Detailed issue description

Steps to reproduce the problem

script.js:

import { SharedArray } from 'k6/data';

const data = new SharedArray('data', function () {
  return JSON.parse(open('./data.json'));
});

export const options = {
  cloud: {
    projectID: 0, // replace with a real project ID
    distribution: {
      private: { loadZone: 'replace-with-a-real-private-load-zone', percent: 100 },
    },
  },
  vus: 1,
  iterations: 1,
};

export default function () {
  console.log(data[0].value);
}

data.json:

[{ "value": "hello" }]
k6 cloud login --token $K6_CLOUD_TOKEN --stack $K6_CLOUD_STACK_URL
k6 archive -O script.tar script.js
k6 cloud run script.tar

For comparison, both of these succeed:

k6 cloud run --local-execution script.tar        # same archive, succeeds
// same script.js/data.json, but with the SharedArray/open() call and its
// usage removed entirely — `k6 cloud run script.tar` (no --local-execution)
// then succeeds too.

Expected behaviour

k6 cloud run script.tar uploads and runs the test the same way it does when the archive has no bundled open()'d files, and the same way --local-execution handles the identical archive.

Actual behaviour

Init   [   0% ] Uploading archive
time="..." level=error msg="uploading test: (400/validation_error) Uploaded content must be a javascript text encoded in UTF-8."
script returned exit code 255

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions