[GH-ISSUE #209] omitempty for boolean values prevent false from being sent to API endpoint #59

Closed
opened 2026-03-03 15:29:56 +03:00 by kerem · 0 comments
Owner

Originally created by @kernel-sanders on GitHub (Aug 15, 2025).
Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/209

When using omitempty on a bool, the value will be omitted if it is false since false is the "zero value" of a bool. This is expected behavior (see https://github.com/golang/go/issues/13284).

Issues arise when the Proxmox default for a bool field is 1 or true as it is not possible to send an explicitly 0 or false due to the omitempty flag on the json marshaler.

Example - Creating an API Token without privilege separation

func createProxmoxAPITokenForUserWithClient(proxmoxClient *goproxmox.Client, userid string) (string, string, error) {
	goProxmoxUserObject, err := proxmoxClient.User(context.Background(), userid)
	if err != nil {
		log.Fatalf("Failed to retrieve created user: %v", err)
		return "", "", errors.New("failed to retrieve created user")
	}

	token := goproxmox.Token{
		TokenID: "my-token",
		Comment: "Arbitrary comment",
		Privsep: false, // This token has the same permissions as the user
	}

	apiToken, err := goProxmoxUserObject.NewAPIToken(context.Background(), token)
	if err != nil {
		return "", "", errors.New("failed to create API token")
	}
	return apiToken.FullTokenID, apiToken.Value, nil
}

This creates an API token for a user, but privilege separation is enabled, which is the default for the Proxmox API.

Potential Solutions

There are two ways I see to handle this:

  1. Remove all omitempty flags from bool values
  2. Use a *bool as the value, as it effectively is a ternary (nil, true, or false).

Option 1 is probably the simplest solution, and I'll open a PR that accomplishes it.

Affected API Calls

I've looked through the codebase and this error likely effects the following API calls:

1. User Creation and Updates, API Token Creation

  • Struct: NewUser
  • Field: Enable bool `json:"enable,omitempty"`
  • Problem: When creating a new user via /access/users, the API defaults to creating the user in an enabled state (enable=1). If you try to create a user that is disabled from the start by setting Enable: false, the field will be omitted, and Proxmox will create an enabled user anyway.

  • Struct: User
  • Field: Enable IntOrBool `json:"enable,omitempty"`
  • Problem: The same issue occurs when updating an existing user via PUT /access/users/{userid}. If you want to disable an active user by setting Enable: false, the omitempty tag will cause the field to be dropped from the request. Since the API does not receive the enable parameter, it makes no change, and the user remains enabled.

  • Struct: Token
  • Field: Privsep IntOrBool `json:"privsep,omitempty"`
  • Problem: When creating an API token for a user, the API defaults to enabling privilege separation (privsep=1). If you try to create an API key with privilege separation disabled by setting Pivsep: false, the field will be omitted, and Proxmox will create an API token with privilege separation enabled anyway.

2. Access Control Lists (ACLs)

  • Struct: ACL (used when updating ACLs)
  • Field: Propagate IntOrBool json:"propagate,omitempty"`
  • Problem: When creating or updating an ACL, the propagate option defaults to 1 (true), meaning the permissions apply to child objects in the hierarchy. If you want to create a permission that applies only to the specified path and not its children (Propagate: false), the field will be omitted, and the API will default to enabling propagation.

3. Domain Management

  • Struct: Domain
  • Field: Verify IntOrBool `json:"verify,omitempty"`
  • Problem: When configuring an LDAP or AD domain, the verify option (to verify the server's TLS certificate) defaults to 1 (true). If you are in a test environment and need to disable this verification by setting Verify: false, the field will be omitted from the request, and the API will enforce certificate verification by default, likely causing the connection to fail.

4. Storage and Downloads

  • Struct: StorageDownloadURLOptions
  • Field: VerifyCertificates IntOrBool `json:"verify-certificates,omitempty"`
  • Problem: This is identical to the Domain.Verify issue. When downloading an ISO or template from a URL, the API defaults to verifying the remote server's TLS certificate (verify-certificates=1). To download from a source with a self-signed certificate, you would need to set VerifyCertificates: false. Due to omitempty, this is not possible, as the field will be dropped and the API will default to true.

5. Virtual Machine Backups (vzdump)

  • Struct: VirtualMachineBackupOptions
  • Field: Remove bool `json:"remove,omitempty"`
  • Problem: The remove flag in the backup API controls whether the temporary lock on a VM is removed after the backup completes. It defaults to 1 (true). In certain scripting scenarios, you might want to keep the VM locked after a backup (Remove: false). This is impossible because setting it to false causes it to be omitted, and the API defaults to removing the lock.

  • Struct: VirtualMachineBackupOptions
  • Field: StdExcludes bool `json:"stdexcludes,omitempty"`
  • Problem: This flag controls whether standard temporary file system mount points are excluded from the backup, and it defaults to 1 (true). If you had a specific need to include these temporary file systems in your backup by setting StdExcludes: false, the field would be omitted, and the API would default to excluding them.
Originally created by @kernel-sanders on GitHub (Aug 15, 2025). Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/209 When using `omitempty` on a `bool`, the value will be omitted if it is `false` since `false` is the "zero value" of a `bool`. This is expected behavior (see https://github.com/golang/go/issues/13284). Issues arise when the Proxmox default for a `bool` field is `1` or `true` as it is not possible to send an explicitly `0` or `false` due to the `omitempty` flag on the json marshaler. ## Example - Creating an API Token without privilege separation ``` func createProxmoxAPITokenForUserWithClient(proxmoxClient *goproxmox.Client, userid string) (string, string, error) { goProxmoxUserObject, err := proxmoxClient.User(context.Background(), userid) if err != nil { log.Fatalf("Failed to retrieve created user: %v", err) return "", "", errors.New("failed to retrieve created user") } token := goproxmox.Token{ TokenID: "my-token", Comment: "Arbitrary comment", Privsep: false, // This token has the same permissions as the user } apiToken, err := goProxmoxUserObject.NewAPIToken(context.Background(), token) if err != nil { return "", "", errors.New("failed to create API token") } return apiToken.FullTokenID, apiToken.Value, nil } ``` This creates an API token for a user, but privilege separation is enabled, which is the default for the Proxmox API. ## Potential Solutions There are two ways I see to handle this: 1. Remove all `omitempty` flags from `bool` values 2. Use a `*bool` as the value, as it effectively is a ternary (nil, true, or false). Option 1 is probably the simplest solution, and I'll open a PR that accomplishes it. ## Affected API Calls I've looked through the codebase and this error likely effects the following API calls: ### 1. User Creation and Updates, API Token Creation * **Struct:** `NewUser` * **Field:** `` Enable bool `json:"enable,omitempty"` `` * **Problem:** When creating a new user via `/access/users`, the API defaults to creating the user in an **enabled** state (`enable=1`). If you try to create a user that is disabled from the start by setting `Enable: false`, the field will be omitted, and Proxmox will create an enabled user anyway. --- * **Struct:** `User` * **Field:** `` Enable IntOrBool `json:"enable,omitempty"` `` * **Problem:** The same issue occurs when updating an existing user via `PUT /access/users/{userid}`. If you want to disable an active user by setting `Enable: false`, the `omitempty` tag will cause the field to be dropped from the request. Since the API does not receive the `enable` parameter, it makes no change, and the user remains enabled. --- * **Struct:** `Token` * **Field:** `` Privsep IntOrBool `json:"privsep,omitempty"` `` * **Problem:** When creating an API token for a user, the API defaults to enabling privilege separation (`privsep=1`). If you try to create an API key with privilege separation disabled by setting `Pivsep: false`, the field will be omitted, and Proxmox will create an API token with privilege separation enabled anyway. ### 2. Access Control Lists (ACLs) * **Struct:** `ACL` (used when updating ACLs) * **Field:** ` `Propagate IntOrBool ``json:"propagate,omitempty"` `` * **Problem:** When creating or updating an ACL, the `propagate` option defaults to `1` (true), meaning the permissions apply to child objects in the hierarchy. If you want to create a permission that applies *only* to the specified path and not its children (`Propagate: false`), the field will be omitted, and the API will default to enabling propagation. ### 3. Domain Management * **Struct:** `Domain` * **Field:** `` Verify IntOrBool `json:"verify,omitempty"` `` * **Problem:** When configuring an LDAP or AD domain, the `verify` option (to verify the server's TLS certificate) defaults to `1` (true). If you are in a test environment and need to disable this verification by setting `Verify: false`, the field will be omitted from the request, and the API will enforce certificate verification by default, likely causing the connection to fail. ### 4. Storage and Downloads * **Struct:** `StorageDownloadURLOptions` * **Field:** `` VerifyCertificates IntOrBool `json:"verify-certificates,omitempty"` `` * **Problem:** This is identical to the `Domain.Verify` issue. When downloading an ISO or template from a URL, the API defaults to verifying the remote server's TLS certificate (`verify-certificates=1`). To download from a source with a self-signed certificate, you would need to set `VerifyCertificates: false`. Due to `omitempty`, this is not possible, as the field will be dropped and the API will default to `true`. ### 5. Virtual Machine Backups (`vzdump`) * **Struct:** `VirtualMachineBackupOptions` * **Field:** `` Remove bool `json:"remove,omitempty"` `` * **Problem:** The `remove` flag in the backup API controls whether the temporary lock on a VM is removed after the backup completes. It defaults to `1` (true). In certain scripting scenarios, you might want to keep the VM locked after a backup (`Remove: false`). This is impossible because setting it to `false` causes it to be omitted, and the API defaults to removing the lock. --- * **Struct:** `VirtualMachineBackupOptions` * **Field:** `` StdExcludes bool `json:"stdexcludes,omitempty"` `` * **Problem:** This flag controls whether standard temporary file system mount points are excluded from the backup, and it defaults to `1` (true). If you had a specific need to *include* these temporary file systems in your backup by setting `StdExcludes: false`, the field would be omitted, and the API would default to excluding them.
kerem closed this issue 2026-03-03 15:29:56 +03:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/go-proxmox#59
No description provided.