Remove the old Go/Mongo API (api/main.go, go.mod, go.sum, .env.example) and switch telemetry backend to PocketBase (http://db.community-scripts.org). Update documentation and flowcharts to reflect the PocketBase collection (_dev_telemetry_data), new REST endpoints (POST/PATCH/GET), field schema, and revised api.func integration (LXC/VM reporting and status updates). Misc scripts and helpers were adjusted (misc/api.func, misc/build.func, misc/error_handler.func) and a new misc/ingest.go was added. This consolidates telemetry to a hosted PocketBase instance and updates docs and integration points accordingly.
17 KiB
api.func Functions Reference
Overview
This document provides a comprehensive reference of all functions in api.func, including parameters, dependencies, usage examples, and error handling. The backend is PocketBase hosted at http://db.community-scripts.org.
Configuration Variables
| Variable | Value | Description |
|---|---|---|
PB_URL |
http://db.community-scripts.org |
PocketBase server URL |
PB_COLLECTION |
_dev_telemetry_data |
PocketBase collection name |
PB_API_URL |
${PB_URL}/api/collections/${PB_COLLECTION}/records |
Full API endpoint |
PB_RECORD_ID |
(runtime) | Stores the PocketBase record ID returned by POST for later PATCH calls |
Function Categories
Error Description Functions
explain_exit_code()
Purpose: Convert numeric exit codes to human-readable explanations Parameters:
$1— Exit code to explain Returns: Human-readable error explanation string Side Effects: None Dependencies: None Environment Variables Used: None
Note
:
explain_exit_code()is the canonical function for exit-code mapping. It is used by bothapi.func(telemetry) anderror_handler.func(error display).
Supported Exit Code Ranges (non-overlapping):
| Range | Category |
|---|---|
| 1–2 | Generic / Shell |
| 6–35 | curl / wget |
| 100–102 | APT / Package manager |
| 124–143 | System / Signals |
| 150–154 | Systemd / Service |
| 160–162 | Python / pip / uv |
| 170–173 | PostgreSQL |
| 180–183 | MySQL / MariaDB |
| 190–193 | MongoDB |
| 200–231 | Proxmox custom codes |
| 243–249 | Node.js / npm |
| 255 | DPKG fatal |
Usage Example:
error_msg=$(explain_exit_code 127)
echo "Error 127: $error_msg"
# Output: Error 127: Command not found
Error Code Examples:
explain_exit_code 1 # "General error / Operation not permitted"
explain_exit_code 22 # "curl: HTTP error returned (404, 429, 500+)"
explain_exit_code 127 # "Command not found"
explain_exit_code 200 # "Proxmox: Failed to create lock file"
explain_exit_code 255 # "DPKG: Fatal internal error"
explain_exit_code 999 # "Unknown error"
API Communication Functions
post_to_api()
Purpose: Create an LXC container telemetry record in PocketBase Parameters: None (uses environment variables) Returns: None Side Effects:
- Sends HTTP POST to
PB_API_URL - Stores the returned PocketBase record
idinPB_RECORD_IDfor later PATCH updates Dependencies:curlcommand Environment Variables Used:DIAGNOSTICS,RANDOM_UUID,CT_TYPE,DISK_SIZE,CORE_COUNT,RAM_SIZE,var_os,var_version,NSAPP,METHOD
Prerequisites:
curlmust be availableDIAGNOSTICSmust be"yes"RANDOM_UUIDmust be set and not empty
API Endpoint: POST http://db.community-scripts.org/api/collections/_dev_telemetry_data/records
JSON Payload:
{
"ct_type": 1,
"type": "lxc",
"disk_size": 8,
"core_count": 2,
"ram_size": 2048,
"os_type": "debian",
"os_version": "12",
"nsapp": "plex",
"method": "install",
"pve_version": "8.0",
"status": "installing",
"random_id": "uuid-string"
}
Response Handling:
- On HTTP 200/201,
PB_RECORD_IDis extracted from the response JSON ("id"field) - On failure, the function returns silently without blocking the installation
Usage Example:
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export NSAPP="plex"
export METHOD="install"
post_to_api
# PB_RECORD_ID is now set (e.g. "abc123def456789")
post_to_api_vm()
Purpose: Create a VM telemetry record in PocketBase Parameters: None (uses environment variables) Returns: None Side Effects:
- Sends HTTP POST to
PB_API_URL - Stores the returned PocketBase record
idinPB_RECORD_IDDependencies:curlcommand, diagnostics file Environment Variables Used:RANDOM_UUID,DISK_SIZE,CORE_COUNT,RAM_SIZE,var_os,var_version,NSAPP,METHOD
Prerequisites:
/usr/local/community-scripts/diagnosticsfile must existDIAGNOSTICSmust be"yes"in that file (read at runtime)curlmust be availableRANDOM_UUIDmust be set and not empty
API Endpoint: POST http://db.community-scripts.org/api/collections/_dev_telemetry_data/records
JSON Payload:
{
"ct_type": 2,
"type": "vm",
"disk_size": 20,
"core_count": 4,
"ram_size": 4096,
"os_type": "ubuntu",
"os_version": "22.04",
"nsapp": "nextcloud",
"method": "install",
"pve_version": "8.0",
"status": "installing",
"random_id": "uuid-string"
}
Note
:
DISK_SIZEis stripped of itsGsuffix before sending (e.g."20G"→20).
Usage Example:
# Create diagnostics file
mkdir -p /usr/local/community-scripts
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
export RANDOM_UUID="$(uuidgen)"
export DISK_SIZE="20G"
export CORE_COUNT=4
export RAM_SIZE=4096
export var_os="ubuntu"
export var_version="22.04"
export NSAPP="nextcloud"
export METHOD="install"
post_to_api_vm
# PB_RECORD_ID is now set
post_update_to_api()
Purpose: Update an existing PocketBase record with installation completion status via PATCH Parameters:
$1— Status ("done","success", or"failed"; default:"failed")$2— Exit code (numeric, default:1) Returns: None Side Effects:- Sends HTTP PATCH to
PB_API_URL/{record_id} - Sets
POST_UPDATE_DONE=trueto prevent duplicate calls Dependencies:curl,explain_exit_code()Environment Variables Used:DIAGNOSTICS,RANDOM_UUID,PB_RECORD_ID
Prerequisites:
curlmust be availableDIAGNOSTICSmust be"yes"RANDOM_UUIDmust be set and not emptyPOST_UPDATE_DONEmust not be"true"(prevents duplicate updates)
Record Lookup:
- If
PB_RECORD_IDis already set (from a priorpost_to_api/post_to_api_vmcall), it is used directly. - Otherwise, the function performs a GET lookup:
GET PB_API_URL?filter=(random_id='<RANDOM_UUID>')&fields=id&perPage=1 - If no record is found, the function sets
POST_UPDATE_DONE=trueand returns.
Status Mapping (PocketBase select field values: installing, sucess, failed, unknown):
| Input Status | PocketBase status |
exit_code |
error |
|---|---|---|---|
"done" / "success" / "sucess" |
"sucess" |
0 |
"" |
"failed" |
"failed" |
from $2 | from explain_exit_code() |
| anything else | "unknown" |
from $2 | from explain_exit_code() |
Note
: The PocketBase schema intentionally spells success as
"sucess".
API Endpoint: PATCH http://db.community-scripts.org/api/collections/_dev_telemetry_data/records/{record_id}
JSON Payload:
{
"status": "sucess",
"error": "",
"exit_code": 0
}
or for failures:
{
"status": "failed",
"error": "Command not found",
"exit_code": 127
}
Usage Example:
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# After a successful installation
post_update_to_api "done" 0
# After a failed installation
post_update_to_api "failed" 127
Function Call Hierarchy
API Communication Flow
post_to_api()
├── Check curl availability
├── Check DIAGNOSTICS == "yes"
├── Check RANDOM_UUID is set
├── Get PVE version
├── Create JSON payload (ct_type=1, type="lxc", status="installing")
├── POST to PB_API_URL
└── Extract PB_RECORD_ID from response
post_to_api_vm()
├── Read DIAGNOSTICS from /usr/local/community-scripts/diagnostics
├── Check curl availability
├── Check DIAGNOSTICS == "yes"
├── Check RANDOM_UUID is set
├── Strip 'G' suffix from DISK_SIZE
├── Get PVE version
├── Create JSON payload (ct_type=2, type="vm", status="installing")
├── POST to PB_API_URL
└── Extract PB_RECORD_ID from response
post_update_to_api(status, exit_code)
├── Check curl availability
├── Check POST_UPDATE_DONE flag
├── Check DIAGNOSTICS == "yes"
├── Check RANDOM_UUID is set
├── Map status → pb_status ("done"→"sucess", "failed"→"failed", *→"unknown")
├── For failed/unknown: call explain_exit_code(exit_code)
├── Resolve record_id (PB_RECORD_ID or GET lookup by random_id)
├── PATCH to PB_API_URL/{record_id}
└── Set POST_UPDATE_DONE=true
Error Description Flow
explain_exit_code(code)
├── Match code against case statement (non-overlapping ranges)
├── Return description string
└── Default: "Unknown error"
Error Code Reference
Generic / Shell (1–2)
| Code | Description |
|---|---|
| 1 | General error / Operation not permitted |
| 2 | Misuse of shell builtins (e.g. syntax error) |
curl / wget (6–35)
| Code | Description |
|---|---|
| 6 | curl: DNS resolution failed (could not resolve host) |
| 7 | curl: Failed to connect (network unreachable / host down) |
| 22 | curl: HTTP error returned (404, 429, 500+) |
| 28 | curl: Operation timeout (network slow or server not responding) |
| 35 | curl: SSL/TLS handshake failed (certificate error) |
APT / Package Manager (100–102)
| Code | Description |
|---|---|
| 100 | APT: Package manager error (broken packages / dependency problems) |
| 101 | APT: Configuration error (bad sources.list, malformed config) |
| 102 | APT: Lock held by another process (dpkg/apt still running) |
System / Signals (124–143)
| Code | Description |
|---|---|
| 124 | Command timed out (timeout command) |
| 126 | Command invoked cannot execute (permission problem?) |
| 127 | Command not found |
| 128 | Invalid argument to exit |
| 130 | Terminated by Ctrl+C (SIGINT) |
| 134 | Process aborted (SIGABRT — possibly Node.js heap overflow) |
| 137 | Killed (SIGKILL / Out of memory?) |
| 139 | Segmentation fault (core dumped) |
| 141 | Broken pipe (SIGPIPE — output closed prematurely) |
| 143 | Terminated (SIGTERM) |
Systemd / Service (150–154)
| Code | Description |
|---|---|
| 150 | Systemd: Service failed to start |
| 151 | Systemd: Service unit not found |
| 152 | Permission denied (EACCES) |
| 153 | Build/compile failed (make/gcc/cmake) |
| 154 | Node.js: Native addon build failed (node-gyp) |
Python / pip / uv (160–162)
| Code | Description |
|---|---|
| 160 | Python: Virtualenv / uv environment missing or broken |
| 161 | Python: Dependency resolution failed |
| 162 | Python: Installation aborted (permissions or EXTERNALLY-MANAGED) |
PostgreSQL (170–173)
| Code | Description |
|---|---|
| 170 | PostgreSQL: Connection failed (server not running / wrong socket) |
| 171 | PostgreSQL: Authentication failed (bad user/password) |
| 172 | PostgreSQL: Database does not exist |
| 173 | PostgreSQL: Fatal error in query / syntax |
MySQL / MariaDB (180–183)
| Code | Description |
|---|---|
| 180 | MySQL/MariaDB: Connection failed (server not running / wrong socket) |
| 181 | MySQL/MariaDB: Authentication failed (bad user/password) |
| 182 | MySQL/MariaDB: Database does not exist |
| 183 | MySQL/MariaDB: Fatal error in query / syntax |
MongoDB (190–193)
| Code | Description |
|---|---|
| 190 | MongoDB: Connection failed (server not running) |
| 191 | MongoDB: Authentication failed (bad user/password) |
| 192 | MongoDB: Database not found |
| 193 | MongoDB: Fatal query error |
Proxmox Custom Codes (200–231)
| Code | Description |
|---|---|
| 200 | Proxmox: Failed to create lock file |
| 203 | Proxmox: Missing CTID variable |
| 204 | Proxmox: Missing PCT_OSTYPE variable |
| 205 | Proxmox: Invalid CTID (<100) |
| 206 | Proxmox: CTID already in use |
| 207 | Proxmox: Password contains unescaped special characters |
| 208 | Proxmox: Invalid configuration (DNS/MAC/Network format) |
| 209 | Proxmox: Container creation failed |
| 210 | Proxmox: Cluster not quorate |
| 211 | Proxmox: Timeout waiting for template lock |
| 212 | Proxmox: Storage type 'iscsidirect' does not support containers (VMs only) |
| 213 | Proxmox: Storage type does not support 'rootdir' content |
| 214 | Proxmox: Not enough storage space |
| 215 | Proxmox: Container created but not listed (ghost state) |
| 216 | Proxmox: RootFS entry missing in config |
| 217 | Proxmox: Storage not accessible |
| 218 | Proxmox: Template file corrupted or incomplete |
| 219 | Proxmox: CephFS does not support containers — use RBD |
| 220 | Proxmox: Unable to resolve template path |
| 221 | Proxmox: Template file not readable |
| 222 | Proxmox: Template download failed |
| 223 | Proxmox: Template not available after download |
| 224 | Proxmox: PBS storage is for backups only |
| 225 | Proxmox: No template available for OS/Version |
| 231 | Proxmox: LXC stack upgrade failed |
Node.js / npm (243–249)
| Code | Description |
|---|---|
| 243 | Node.js: Out of memory (JavaScript heap out of memory) |
| 245 | Node.js: Invalid command-line option |
| 246 | Node.js: Internal JavaScript Parse Error |
| 247 | Node.js: Fatal internal error |
| 248 | Node.js: Invalid C++ addon / N-API failure |
| 249 | npm/pnpm/yarn: Unknown fatal error |
DPKG (255)
| Code | Description |
|---|---|
| 255 | DPKG: Fatal internal error |
Default
| Code | Description |
|---|---|
| * | Unknown error |
Environment Variable Dependencies
Required Variables
DIAGNOSTICS: Enable/disable diagnostic reporting ("yes"/"no")RANDOM_UUID: Unique identifier for session tracking
Container / VM Variables
CT_TYPE: Container type (1for LXC,2for VM)DISK_SIZE: Disk size in GB (VMs may includeGsuffix)CORE_COUNT: Number of CPU coresRAM_SIZE: RAM size in MBvar_os: Operating system typevar_version: OS versionNSAPP: Application nameMETHOD: Installation method
Internal Variables
PB_URL: PocketBase server URLPB_COLLECTION: PocketBase collection namePB_API_URL: Full PocketBase API endpointPB_RECORD_ID: PocketBase record ID (set after POST, used for PATCH)POST_UPDATE_DONE: Flag to prevent duplicate status updatesJSON_PAYLOAD: API request payload (local to each function)RESPONSE: API response (local to each function)
Error Handling Patterns
API Communication Errors
- All API functions return silently on failure — network errors never block installation
- Missing prerequisites (no curl, diagnostics disabled, no UUID) cause early return
POST_UPDATE_DONEflag prevents duplicate PATCH updates- PocketBase record lookup falls back to
GET ?filter=(random_id='...')ifPB_RECORD_IDis unset
Error Description Errors
- Unknown error codes return
"Unknown error" - All recognized codes are handled via a
casestatement with non-overlapping ranges - The fallback message is generic (no error code is embedded)
Integration Examples
With build.func (LXC)
#!/usr/bin/env bash
source core.func
source api.func
source build.func
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report LXC installation start → POST creates record
post_to_api
# ... container creation via build.func ...
# Report completion → PATCH updates record
if [[ $? -eq 0 ]]; then
post_update_to_api "done" 0
else
post_update_to_api "failed" $?
fi
With vm-core.func (VM)
#!/usr/bin/env bash
source core.func
source api.func
source vm-core.func
export RANDOM_UUID="$(uuidgen)"
# Report VM installation start → POST creates record
post_to_api_vm
# ... VM creation via vm-core.func ...
# Report completion → PATCH updates record
post_update_to_api "done" 0
With error_handler.func
#!/usr/bin/env bash
source core.func
source error_handler.func
source api.func
error_code=127
error_msg=$(explain_exit_code $error_code)
echo "Error $error_code: $error_msg"
# Report error to PocketBase
post_update_to_api "failed" $error_code
Best Practices
API Usage
- Always check prerequisites before API calls (handled internally by each function)
- Call
post_to_api/post_to_api_vmonce at installation start to get aPB_RECORD_ID - Call
post_update_to_apionce at the end to finalize the record via PATCH - Never block the installation on API failures
Error Reporting
- Use
explain_exit_code()for human-readable error messages - Pass the actual numeric exit code to
post_update_to_api - Report both success (
"done") and failure ("failed") cases - The
POST_UPDATE_DONEflag automatically prevents duplicate updates
Diagnostic Reporting
- Respect user privacy — only send data when
DIAGNOSTICS="yes" - Use anonymous random UUIDs for session tracking (no personal data)
- Include relevant system information (PVE version, OS, app name)
- The diagnostics file at
/usr/local/community-scripts/diagnosticscontrols VM reporting