📄 Description
When creating a snapshot the API does not differ between LXC Container and Qemu VMs. Qemu VMs need the attribute vmstate, while it is not needed for LXC VMs . This leads to an error on the API side when creating a snapshot of an LXC Container.
👣 Steps to reproduce
For this to work you need to have at least one LXC VM
- Try to create a Snapshot using the Create function in the snapshot.go file with the ConfigSnapshot struct
package main
import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
proxmox "github.com/Telmate/proxmox-api-go/proxmox"
"github.com/joho/godotenv"
)
func main() {
fmt.Println("Backend running")
http.HandleFunc("/snapshot/create", CreateSnapshot)
log.Fatal(http.ListenAndServe(":8080", nil))
}
type CreateSnapshotRequest struct {
VMID uint32 `json:"vmid"`
Name string `json:"name"`
Description string `json:"description"`
}
// loadEnv ensures .env is loaded and returns Proxmox API credentials
func loadEnv() (string, string, string, error) {
if err := godotenv.Load("./.env"); err != nil {
return "", "", "", fmt.Errorf("failed to load .env: %w", err)
}
apiURL := os.Getenv("API_URL")
tokenID := os.Getenv("TOKEN_ID")
tokenSecret := os.Getenv("TOKEN_SECRET")
if apiURL == "" || tokenID == "" || tokenSecret == "" {
return "", "", "", fmt.Errorf("missing required environment variables")
}
return apiURL, tokenID, tokenSecret, nil
}
func enableCors(w http.ResponseWriter) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
}
func newProxmoxClient(ctx context.Context) (*proxmox.Client, error) {
apiURL, tokenID, tokenSecret, err := loadEnv()
if err != nil {
return nil, err
}
tlsConfig := &tls.Config{InsecureSkipVerify: true}
hclient := &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsConfig},
}
client, err := proxmox.NewClient(apiURL, hclient, "", tlsConfig, "", 300)
if err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
}
client.SetAPIToken(tokenID, tokenSecret)
return client, nil
}
func CreateSnapshot(w http.ResponseWriter, r *http.Request) {
enableCors(w)
// Preflight-Request behandeln
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
// Nur POST zulassen
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var req CreateSnapshotRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid JSON body: "+err.Error(), http.StatusBadRequest)
return
}
fmt.Println("VMID:", req.VMID)
fmt.Println("Name:", req.Name)
fmt.Println("Description:", req.Description)
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
defer cancel()
client, err := newProxmoxClient(ctx)
if err != nil {
http.Error(w, "Failed to connect to Proxmox", http.StatusInternalServerError)
return
}
vmr, err := client.GetVmRefById(ctx, proxmox.GuestID(req.VMID))
if err != nil {
log.Printf("failed to get VM ref: %v", err)
http.Error(w, "Failed to get VM ref: "+err.Error(), http.StatusInternalServerError)
return
}
snapshot := proxmox.ConfigSnapshot{
Name: proxmox.SnapshotName(req.Name),
Description: req.Description,
}
// Those methods were copied from the Create-method only the print statements were inserted for debugging purposes
if err = client.CheckVmRef(ctx, vmr); err != nil {
fmt.Printf("VMRef %v\n", err)
}
if err = snapshot.Validate(); err != nil {
fmt.Printf("Snapshot %v\n", err)
}
if err := snapshot.CreateNoCheck(ctx, client, vmr); err != nil {
log.Printf("failed to create snapshot: %v\n", err)
http.Error(w, "Failed to create snapshot: ", http.StatusInternalServerError)
return
}
}
❌ Current behaviour
This leads to the following error:
2025/12/02 15:05:58 failed to create snapshot: error creating Snapshot: 400 Parameter verification failed., (params: {"description":"Test3","snapname":"Test3","vmstate":false})
Leaving out the vmstate false in the struct leads to the same error, as the vmstate is automatically replaced.
Using the Proxmox UI I am able to create snapshots as usual.
✔ Expected behaviour
Snapshot creation should differ between Qemu VMs and LXC Containers and send the attributes according to the Proxmox API:
LXC: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/lxc/{vmid}/snapshot
Qemu: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/qemu/{vmid}/snapshot
📄 Description
When creating a snapshot the API does not differ between LXC Container and Qemu VMs. Qemu VMs need the attribute vmstate, while it is not needed for LXC VMs . This leads to an error on the API side when creating a snapshot of an LXC Container.
👣 Steps to reproduce
For this to work you need to have at least one LXC VM
❌ Current behaviour
This leads to the following error:
2025/12/02 15:05:58 failed to create snapshot: error creating Snapshot: 400 Parameter verification failed., (params: {"description":"Test3","snapname":"Test3","vmstate":false})
Leaving out the vmstate false in the struct leads to the same error, as the vmstate is automatically replaced.
Using the Proxmox UI I am able to create snapshots as usual.
✔ Expected behaviour
Snapshot creation should differ between Qemu VMs and LXC Containers and send the attributes according to the Proxmox API:
LXC: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/lxc/{vmid}/snapshot
Qemu: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/qemu/{vmid}/snapshot