{"record":{"id":"36502f3dd57d60fd","repo":"argoproj/argo-workflows","slug":"not-supported-when-you-are-in-offline-mode","errorCode":null,"errorMessage":"not supported when you are in offline mode","messagePattern":"not supported when you are in offline mode","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiclient/offline-client.go","lineNumber":39,"sourceCode":"\nfunc (m offlineWorkflowTemplateGetterMap) GetNamespaceGetter(namespace string) templateresolution.WorkflowTemplateNamespacedGetter {\n\tv := m[namespace]\n\tif v == nil {\n\t\treturn offlineWorkflowTemplateNamespacedGetter{\n\t\t\tworkflowTemplates: map[string]*wfv1.WorkflowTemplate{},\n\t\t\tnamespace:         namespace,\n\t\t}\n\t}\n\n\treturn m[namespace]\n}\n\ntype offlineClient struct {\n\tclusterWorkflowTemplateGetter       templateresolution.ClusterWorkflowTemplateGetter\n\tnamespacedWorkflowTemplateGetterMap offlineWorkflowTemplateGetterMap\n}\n\nvar ErrOffline = fmt.Errorf(\"not supported when you are in offline mode\")\n\nvar _ Client = &offlineClient{}\n\n// newOfflineClient creates a client that keeps all files (or files recursively contained within a path) given to it in memory.\n// It is useful for linting a set of files without having to connect to a cluster.\nfunc newOfflineClient(ctx context.Context, paths []string) (context.Context, Client, error) {\n\tclusterWorkflowTemplateGetter := &offlineClusterWorkflowTemplateGetter{\n\t\tclusterWorkflowTemplates: map[string]*wfv1.ClusterWorkflowTemplate{},\n\t}\n\tworkflowTemplateGetters := offlineWorkflowTemplateGetterMap{}\n\tfor _, basePath := range paths {\n\t\terr := file.WalkManifests(ctx, basePath, func(path string, bytes []byte) error {\n\t\t\tfor _, pr := range common.ParseObjects(ctx, bytes, false) {\n\t\t\t\tobj, err := pr.Object, pr.Err\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to parse YAML from file %s: %w\", path, err)\n\t\t\t\t}\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/pkg/apiclient/offline-client.go#L21-L57","documentation":"ErrOffline is the sentinel error returned by every unsupported operation of the offline API client. The offline client exists so `argo lint` and the offline apiclient transport can validate files without a cluster; it only stores WorkflowTemplates/ClusterWorkflowTemplates in memory. Any service method outside that scope (cluster workflow template writes, cron workflow creation, etc.) deliberately fails with this error instead of connecting.","triggerScenarios":"Calling CreateClusterWorkflowTemplate, GetClusterWorkflowTemplate, ListClusterWorkflowTemplates, UpdateClusterWorkflowTemplate, DeleteClusterWorkflowTemplate, or CreateCronWorkflow on an OfflineClusterWorkflowTemplateServiceClient, which is what the apiclient returns when the client is constructed in offline mode (e.g. `argo lint` or apiclient's offline transport).","commonSituations":"Running `argo lint` on files that contain ClusterWorkflowTemplates or CronWorkflows and invoking code paths that try to fetch/create those resources; reusing an offline-constructed client for operations it was never meant to perform; tests or tools built on pkg/apiclient that assume a live server.","solutions":["Do not call cluster-workflow-template or cron-workflow operations through an offline client; use a real client (argo server gRPC or direct-kube transport) for those operations.","Restructure the lint/validate path to only rely on template resolution (templateresolution uses the in-memory getters), not full service clients.","If you need to detect this case programmatically, compare the returned error against pkg/apiclient.ErrOffline with errors.Is before falling back to a connected client."],"exampleFix":"// before\nwfTmpl, err := cwftClient.Get(ctx, req) // offline client -> ErrOffline\n// after\nif errors.Is(err, apiclient.ErrOffline) {\n    // resolve template locally via templateresolution instead of RPC\n    tmpl, err := templateGetter.Get(ctx, req)\n}","handlingStrategy":"try-catch","validationCode":"if client is apiclient.Client {\n    _, err := cwftClient.ListClusterWorkflowTemplates(ctx, nil)\n    if errors.Is(err, apiclient.ErrOffline) {\n        // switch to a connected client before doing cluster-template ops\n    }\n}","typeGuard":"func isOfflineErr(err error) bool {\n    return errors.Is(err, apiclient.ErrOffline)\n}","tryCatchPattern":"tmpl, err := cwftClient.GetClusterWorkflowTemplate(ctx, req)\nif err != nil {\n    if errors.Is(err, apiclient.ErrOffline) {\n        tmpl, err = localTemplateGetter.Get(ctx, req.Name)\n    }\n    if err != nil { return err }\n}","preventionTips":["Only use the offline client for lint/validate flows; construct a server or direct-kube client for CRUD operations.","Check errors.Is(err, apiclient.ErrOffline) whenever the transport of your client may vary.","Keep cluster-template/cron-workflow code paths out of offline lint tooling."],"tags":["go","offline-mode","apiclient","lint"],"backgroundTag":"operation-not-supported-in-offline-mode","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}