{"record":{"id":"270f091f97d58d4e","repo":"nektos/act","slug":"copytarstream-has-been-cancelled","errorCode":null,"errorMessage":"CopyTarStream has been cancelled","messagePattern":"CopyTarStream has been cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/container/host_environment.go","lineNumber":83,"sourceCode":"\tif err := os.RemoveAll(destPath); err != nil {\n\t\treturn err\n\t}\n\ttr := tar.NewReader(tarStream)\n\tcp := &filecollector.CopyCollector{\n\t\tDstDir: destPath,\n\t}\n\tfor {\n\t\tti, err := tr.Next()\n\t\tif errors.Is(err, io.EOF) {\n\t\t\treturn nil\n\t\t} else if err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif ti.FileInfo().IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tif ctx.Err() != nil {\n\t\t\treturn fmt.Errorf(\"CopyTarStream has been cancelled\")\n\t\t}\n\t\tif err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\nfunc (e *HostEnvironment) CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor {\n\treturn func(ctx context.Context) error {\n\t\tlogger := common.Logger(ctx)\n\t\tsrcPrefix := filepath.Dir(srcPath)\n\t\tif !strings.HasSuffix(srcPrefix, string(filepath.Separator)) {\n\t\t\tsrcPrefix += string(filepath.Separator)\n\t\t}\n\t\tlogger.Debugf(\"Stripping prefix:%s src:%s\", srcPrefix, srcPath)\n\t\tvar ignorer gitignore.Matcher\n\t\tif useGitIgnore {\n\t\t\tps, err := gitignore.ReadPatterns(polyfill.New(osfs.New(srcPath)), nil)","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/container/host_environment.go#L65-L101","documentation":"Thrown by HostEnvironment.CopyTarStream while extracting a tar stream (e.g. restoring an action, artifact, or cache tarball onto the host filesystem). The loop checks ctx.Err() between tar entries and aborts as soon as the context is cancelled. It means the caller (job step, timeout, or Ctrl-C) cancelled the operation mid-extraction, not that the tar data itself is corrupt.","triggerScenarios":"CopyTarStream is invoked with a context that gets cancelled while entries remain: a step timeout fires during extraction, the user interrupts act (SIGINT), or a parent executor in the pipeline returns and cancels the run context.","commonSituations":"Large actions/caches being untarred when a per-job timeout expires; running act interactively and pressing Ctrl-C during 'clone' or 'extract' phases; Docker or artifact download being slow enough that an upstream deadline hits first.","solutions":["If the cancellation was unintentional, raise or remove the step/job timeout that cancelled the context.","Re-run the job; partial extraction means the destination directory may need cleaning before retry.","Check for the real upstream error — this message is a symptom; the root cause is whatever cancelled the context (network stall, slow tar source).","If you call CopyTarStream from Go code, pass a context with a timeout sized to the tar size."],"exampleFix":"# before (workflow)\nsteps:\n  - uses: some/big-action@v1\n    timeout-minutes: 1\n# after\nsteps:\n  - uses: some/big-action@v1\n    timeout-minutes: 10","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := copyTarStream(ctx, r, cp)\nif err != nil {\n  if strings.Contains(err.Error(), 'CopyTarStream has been cancelled') || ctx.Err() != nil {\n    // deliberate cancellation: clean partial output, do not retry blindly\n    os.RemoveAll(dest)\n    return ctx.Err()\n  }\n  return err\n}","preventionTips":["Size context timeouts to the tar size being extracted","Clean destination dirs before extraction so retries start fresh","Log ctx cancellation cause before it propagates into extraction loops"],"tags":["cancellation","context","tar","host-extractor","timeout"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}