Skip to content

Multiple dropdown field causes double JSON encoding on save #1194

@Jerome-Gdrs

Description

@Jerome-Gdrs

Code of Conduct

  • I agree to follow this project's Code of Conduct

Is there an existing issue for this?

  • I have searched the existing issues

GLPI Version

11.0.6

Plugin version

1.24.0

Bug description

When saving a GLPI item (e.g. Computer) that contains a dropdown field with multiple = 1, the stored value in the database becomes double JSON-encoded.

Example: correct value is ["9"], but after save it becomes [["9"]].

This causes a fatal PHP exception on next page load.

Relevant log output

Twig\Error\RuntimeError: "Cannot access offset of type array in isset or empty"
in @fields/fields.html.twig at line 234
triggered via Dropdown::show() at src/Dropdown.php:218

Page URL

/front/computer.form.php?id=13969

Steps To reproduce

  1. Create a container with a dropdown field where multiple = 1
  2. Attach the container to the Computer (or Monitor/Peripheral) itemtype
  3. Open any Computer that has a value saved in that field
  4. Save the form without changing the multiple dropdown field
  5. Reload the page → fatal Twig exception
  6. Check the DB: the column now contains [["9"]] instead of ["9"]

Your GLPI setup information

GLPI information
GLPI: 11.0.6 (/glpidev => /var/www/glpi)
Installation mode: TARBALL
Current language: fr_BE
Source Integrity: 2 files changed
  M: locales/fr_BE.mo
  M: locales/fr_BE.po
Server
Operating system: Linux glpi-dev.example.be 6.1.0-41-amd64 #​1 SMP PREEMPT_DYNAMIC Debian 6.1.158-1 (2025-11-09) x86_64

PHP: 8.4.16 fpm-fcgi

PHP extensions: Core, date, libxml, openssl, pcre, zlib, filter, hash, json, random, Reflection, SPL, session, standard, sodium, cgi-fcgi, mysqlnd, PDO, xml, apcu, bcmath, bz2, calendar, ctype, curl, dom, mbstring, FFI, fileinfo, ftp, gd, gettext, iconv, igbinary, intl, ldap, exif, mysqli, pdo_mysql, Phar, posix, readline, shmop, SimpleXML, soap, sockets, sysvmsg, sysvsem, sysvshm, tokenizer, xmlreader, xmlrpc, xmlwriter, xsl, zip, redis, Zend OPcache

Setup: disable_functions="" max_execution_time="30" max_input_vars="1000" memory_limit="128M" post_max_size="8M" session.cookie_secure="0" session.cookie_httponly="1" session.cookie_samesite="" session.save_handler="files" upload_max_filesize="2M"

Web server: Apache/2.4.66 (Debian) (Apache/2.4.66 (Debian) Server at glpidev.example.be Port 80)

User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:150.0) Gecko/20100101 Firefox/150.0

Database:

Server Software: -- Please help get to 10k stars at https://github.com/MariaDB/Server

Server Version: 11.8.6-MariaDB-0+deb13u1 from Debian

Server SQL Mode: STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Parameters: glpisys@localhost/glpi

Host info: Localhost via UNIX socket

Requirements:
PHP version (8.4.16) is supported.
OS and PHP are relying on 64 bits integers.
Sessions configuration is OK.
Allocated memory is sufficient.
Following extensions are installed: dom, fileinfo, filter, libxml, simplexml, tokenizer, xmlreader, xmlwriter.
mysqli extension is installed
curl extension is installed
gd extension is installed
intl extension is installed
mbstring extension is installed
zlib extension is installed
bcmath extension is installed
The constant SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES is present.
openssl extension is installed
Database engine version (11.8.6) is supported.
The log file has been created successfully.
Write access to /var/www/glpi/files/_cache has been validated.
Write access to /var/www/glpi/files/_cron has been validated.
Write access to /var/www/glpi/files has been validated.
Write access to /var/www/glpi/files/_graphs has been validated.
Write access to /var/www/glpi/files/_lock has been validated.
Write access to /var/www/glpi/files/_pictures has been validated.
Write access to /var/www/glpi/files/_plugins has been validated.
Write access to /var/www/glpi/files/_rss has been validated.
Write access to /var/www/glpi/files/_sessions has been validated.
Write access to /var/www/glpi/files/_tmp has been validated.
Write access to /var/www/glpi/files/_uploads has been validated.

Sessions configuration is secured.
exif extension is installed
ldap extension is installed
Following extensions are installed: bz2, Phar, zip.
Zend OPcache extension is installed
Following extensions are installed: ctype, iconv, sodium.
Write access to /var/www/glpi/marketplace has been validated.
Timezones seems not loaded, see https://glpi-install.readthedocs.io/en/latest/timezones.html.


GLPI constants

GLPI_ROOT: "/var/www/glpi"
GLPI_VERSION: "11.0.6"
GLPI_SCHEMA_VERSION: "11.0.6@84160e91f70f353b33495a7928e5b1476d4b6d98"
GLPI_FILES_VERSION: "11.0.6-15c577a4"
GLPI_MIN_PHP: "8.2"
GLPI_MAX_PHP: "8.5"
GLPI_YEAR: "2026"
GLPI_I18N_DIR: "/var/www/glpi/locales"
GLPI_ENVIRONMENT_TYPE: "production"
GLPI_CONFIG_DIR: "/var/www/glpi/config"
GLPI_VAR_DIR: "/var/www/glpi/files"
GLPI_MARKETPLACE_DIR: "/var/www/glpi/marketplace"
GLPI_ALLOW_IFRAME_IN_RICH_TEXT: false
GLPI_SERVERSIDE_URL_ALLOWLIST: ["^\n (http|https|feed):// # protocol\n (\n (?:\n (?:xn--[a-z0-9-]++\.)*+xn--[a-z0-9-]++ # a domain name using punycode\n |\n (?:[\pL\pN\pS\pM\-\]++\.)+[\pL\pN\pM]++ # a multi-level domain name\n |\n [a-z0-9\-\]++ # a single-level domain name\n )\.?\n | # or\n \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address\n | # or\n \[\n (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))\n \] # an IPv6 address\n )\n (?:/ (?:[\pL\pN\pS\pM\-._\!$&'()+,;=:@]|%[0-9A-Fa-f]{2}) )* # a path\n (?:\? (?:[\pL\pN\-._\~!$&'\\+,;=:@/?]|%[0-9A-Fa-f]{2}) )? # a query (optional)\n $~ixuD"]
GLPI_DISALLOWED_UPLOADS_PATTERN: "/\.(php\d*|phar)$/i"
GLPI_TELEMETRY_URI: "https://telemetry.glpi-project.org"
GLPI_INSTALL_MODE: "TARBALL"
GLPI_NETWORK_MAIL: "glpi@teclib.com"
GLPI_NETWORK_SERVICES: "https://services.glpi-network.com"
GLPI_MARKETPLACE_ENABLE: 3
GLPI_MARKETPLACE_PRERELEASES: false
GLPI_MARKETPLACE_ALLOW_OVERRIDE: true
GLPI_MARKETPLACE_MANUAL_DOWNLOADS: true
GLPI_USER_AGENT_EXTRA_COMMENTS: ""
GLPI_DOCUMENTATION_ROOT_URL: "https://links.glpi-project.org"
GLPI_DISABLE_ONLY_FULL_GROUP_BY_SQL_MODE: "1"
GLPI_LOG_LVL: "warning"
GLPI_SKIP_UPDATES: false
GLPI_STRICT_ENV: false
GLPI_AJAX_DASHBOARD: "1"
GLPI_CALDAV_IMPORT_STATE: 0
GLPI_CENTRAL_WARNINGS: "1"
GLPI_SYSTEM_CRON: false
GLPI_TEXT_MAXSIZE: "4000"
GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING: "0"
GLPI_WEBHOOK_CRA_MANDATORY: false
GLPI_ALTCHA_MODE: "interactive"
GLPI_ALTCHA_MAX_NUMBER: 50000
GLPI_ALTCHA_EXPIRATION_INTERVAL: "PT20M"
GLPI_DOC_DIR: "/var/www/glpi/files"
GLPI_CACHE_DIR: "/var/www/glpi/files/_cache"
GLPI_CRON_DIR: "/var/www/glpi/files/_cron"
GLPI_GRAPH_DIR: "/var/www/glpi/files/_graphs"
GLPI_LOCAL_I18N_DIR: "/var/www/glpi/files/_locales"
GLPI_LOCK_DIR: "/var/www/glpi/files/_lock"
GLPI_LOG_DIR: "/var/www/glpi/files/_log"
GLPI_PICTURE_DIR: "/var/www/glpi/files/_pictures"
GLPI_PLUGIN_DOC_DIR: "/var/www/glpi/files/_plugins"
GLPI_RSS_DIR: "/var/www/glpi/files/_rss"
GLPI_SESSION_DIR: "/var/www/glpi/files/_sessions"
GLPI_TMP_DIR: "/var/www/glpi/files/_tmp"
GLPI_UPLOAD_DIR: "/var/www/glpi/files/_uploads"
GLPI_INVENTORY_DIR: "/var/www/glpi/files/_inventories"
GLPI_THEMES_DIR: "/var/www/glpi/files/_themes"
GLPI_PLUGINS_DIRECTORIES: ["/var/www/glpi/marketplace","/var/www/glpi/plugins"]
GLPI_NETWORK_API_URL: "https://services.glpi-network.com/api"
GLPI_NETWORK_REGISTRATION_API_URL: "https://services.glpi-network.com/api/registration/"
GLPI_MARKETPLACE_PLUGINS_API_URI: "https://services.glpi-network.com/api/marketplace/"

LDAP directories


SQL replicas
Not active
Notifications
Way of sending emails: SMTP(smtp://127.0.0.1:25?verify_peer=0)
Name: 'glpi@example.com'
	Active: No
	Server: '{outlook.office365.com:993/imap-oauth-1/ssl}'
	Login: 'glpi@example.com'
	Password: Yes
Plugins list
fields               Name: Additional fields              Version: 1.24.0       State: Enabled                                  Install Method: Manual
advancedforms        Name: advancedforms                  Version: 1.0.1        State: Enabled                                  Install Method: Manual
datainjection        Name: Data injection                 Version: 2.15.4       State: Enabled                                  Install Method: Manual
glpiinventory        Name: GLPI Inventory                 Version: 1.6.7        State: Enabled                                  Install Method: Manual
oauthimap            Name: OAuth IMAP                     Version: 1.5.0        State: Enabled                                  Install Method: Manual
formcreator          Name: Formcreator End-of-Life Update Version: 3.0.0        State: Not installed                            Install Method: Manual
ocsinventoryng       Name: OCS Inventory NG               Version: 2.0.4        State: Not installed                            Install Method: Manual
webservices          Name: Web Services                   Version: 2.0.0        State: Not installed                            Install Method: Manual

Anything else?

PHP internal working workaround (until fix is applied) — container.class.php ~line 1408

} else {
    $value = $data[$field_name];
    if (is_string($value)) {
        $value = json_decode($value, true) ?? [];
    }
    $value = is_array($value) ? $value : [];
    $value = array_map(fn($v) => is_array($v) ? reset($v) : $v, $value);
    $data[$field_name] = json_encode(array_values($value));
}

This handles all cases:

["9"] (correct PHP array) → unchanged → '["9"]'
[["9"]] (nested array, the bug) → flattened → '["9"]'
'["9"]' (JSON string) → decoded then re-encoded → '["9"]'

DB workaround (internal temporary working patch, until fix is applied)

UPDATE glpi_plugin_fields_computerattributions
SET plugin_fields_accessoiresretourfielddropdowns_id = '["9"]'
WHERE plugin_fields_accessoiresretourfielddropdowns_id = '[["9"]]';

UPDATE glpi_plugin_fields_monitorattributions
SET plugin_fields_accessoiresretourfielddropdowns_id = '["9"]'
WHERE plugin_fields_accessoiresretourfielddropdowns_id = '[["9"]]';

UPDATE glpi_plugin_fields_peripheralattributions
SET plugin_fields_accessoiresretourfielddropdowns_id = '["9"]'
WHERE plugin_fields_accessoiresretourfielddropdowns_id = '[["9"]]';

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions