{"record":{"id":"ea3c234988189a95","repo":"amir20/dozzle","slug":"unknown-action-s","errorCode":null,"errorMessage":"unknown action: %s","messagePattern":"unknown action: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/client.go","lineNumber":419,"sourceCode":"}\n\nfunc (c *Client) ContainerAction(ctx context.Context, containerId string, action container.ContainerAction) error {\n\tvar containerAction pb.ContainerAction\n\tswitch action {\n\tcase container.Start:\n\t\tcontainerAction = pb.ContainerAction_Start\n\n\tcase container.Stop:\n\t\tcontainerAction = pb.ContainerAction_Stop\n\n\tcase container.Restart:\n\t\tcontainerAction = pb.ContainerAction_Restart\n\n\tcase container.Remove:\n\t\tcontainerAction = pb.ContainerAction_Remove\n\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown action: %s\", action)\n\t}\n\n\t_, err := c.client.ContainerAction(ctx, &pb.ContainerActionRequest{ContainerId: containerId, Action: containerAction})\n\n\treturn err\n}\n\nfunc (c *Client) UpdateContainer(ctx context.Context, containerID string, progressCh chan<- container.UpdateProgress) (bool, error) {\n\tdefer close(progressCh)\n\n\tstream, err := c.client.UpdateContainer(ctx, &pb.UpdateContainerRequest{ContainerId: containerID})\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tupdated := false\n\tfor {\n\t\tprogress, err := stream.Recv()","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/agent/client.go#L401-L437","documentation":"ContainerAction returns \"unknown action: %s\" when the given container.ContainerAction value is not one of Start, Stop, Restart, or Remove, so it cannot be mapped to a pb.ContainerAction enum for the gRPC call. It is a programming/client-side error, not a Docker error.","triggerScenarios":"Calling client.ContainerAction(ctx, id, action) with an out-of-range container.ContainerAction value, e.g. a zero-value enum, an action added to container.ContainerAction but not yet mapped in the agent client, or an invalid value cast from an HTTP parameter.","commonSituations":"New container action added to internal/container without updating the switch in the agent client; web handler passing an unvalidated action string converted to the enum; tests constructing the enum with an invalid int.","solutions":["Add the missing case to the switch in ContainerAction (internal/agent/client.go) for the new container.ContainerAction value","Validate user-supplied action input at the HTTP layer against the whitelist (start/stop/restart/remove) before calling the client","Use only the exported container.Start/Stop/Restart/Remove constants, never raw numeric conversions","Extend tests to cover every container.ContainerAction value mapping to a pb enum"],"exampleFix":"// before\naction := container.ContainerAction(strings.TrimSpace(r.URL.Query().Get(\"action\")))\nerr := client.ContainerAction(ctx, id, action)\n// after\nvar action container.ContainerAction\nswitch r.URL.Query().Get(\"action\") {\ncase \"start\": action = container.Start\ncase \"stop\": action = container.Stop\ncase \"restart\": action = container.Restart\ncase \"remove\": action = container.Remove\ndefault:\n    http.Error(w, \"unsupported action\", http.StatusBadRequest)\n    return\n}\nerr := client.ContainerAction(ctx, id, action)","handlingStrategy":"validation","validationCode":"switch action {\ncase container.Start, container.Stop, container.Restart, container.Remove:\n    // ok\ndefault:\n    return fmt.Errorf(\"unsupported action: %s\", action)\n}","typeGuard":"func supportedAction(a container.ContainerAction) bool {\n    switch a { case container.Start, container.Stop, container.Restart, container.Remove: return true }\n    return false\n}","tryCatchPattern":"if err := client.ContainerAction(ctx, id, action); err != nil {\n    if strings.HasPrefix(err.Error(), \"unknown action\") { http.Error(w, \"unsupported action\", 400); return }\n    return err\n}","preventionTips":["Only pass exported container.Start/Stop/Restart/Remove constants; never cast raw strings/ints to the enum","When adding a new container.ContainerAction, update the mapping switch and tests in internal/agent/client.go","Whitelist actions at the HTTP handler layer before invoking the client"],"tags":["go","grpc","agent","enum","validation"],"backgroundTag":"unsupported-enum-value","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}