Skip to content

[6.x]: UploadController::upload throws TypeError when elementId is posted as a string (which it always is, from form data) #18945

@blessingefkt

Description

@blessingefkt

What happened?

Description

Assets\UploadController::upload throws a TypeError whenever an asset
field is configured with a dynamic subpath (e.g. {uid}) and a user
uploads a file directly from the entry editor.

TypeError: CraftCms\Cms\Element\Elements::getElementById():
  Argument #1 ($elementId) must be of type int, string given

The dynamic-subpath case is the one that takes the getElementById($elementId, ...)
branch in UploadController::upload — Craft needs the element to resolve
the {uid} (or {slug}, etc.) template variable into a real folder. Form-
encoded request data is always strings on the PHP side, but
Elements::getElementById() declares strict int $elementId, so PHP 8's
strict types throw before the resolve can run.

Static-subpath fields don't hit this codepath: when the upload location
resolves to a fixed folder, folderId is already populated and the
elementId branch is skipped.

The two neighbouring calls in the same method (folderId, fieldId)
already use $request->integer(...), so this looks like a missed-spot
consistency bug rather than an intentional design choice.

Steps to reproduce

  1. Spin up a fresh Craft 6.0.0-alpha.4 install on PHP 8.5 (strict types).
  2. Create a Channel section ("Hub Resources" in my repro) with an Assets
    field ("Cover Image" in my repro).
  3. In the field's settings, under Default Upload Location:
    • Volume: pick any volume (in my repro: "Hub Resource Assets",
      an R2-backed volume — same behaviour on local volumes)
    • Subpath: {uid} (any template variable will do; the bug fires on
      any non-empty subpath that needs element context to resolve)
  4. Save the field, open an entry that uses it, and click Upload files
    on the field. Choose any file.

The browser posts to admin/actions/assets/upload with form data:

fieldId: 8
elementId: 18
siteId: 1
_token: …
assets-upload: (binary)

The request 500s instead of completing the upload.

Expected behavior

The upload completes and the asset is created in the resolved folder.

Actual behavior

TypeError in
Elements::getElementById()
because $elementId arrives as "18" (string) rather than 18 (int).

Stack trace:

TypeError: CraftCms\Cms\Element\Elements::getElementById():
  Argument #1 ($elementId) must be of type int, string given,
  called in /var/www/html/vendor/craftcms/cms/src/Http/Controllers/Assets/UploadController.php on line 68

Craft CMS version

6.0.0-alpha.4

PHP version

PHP 8.5.5

Operating system and version

macOS 26.3 (host) Debian GNU/Linux 13 (trixie) (DDEV web container)

Database type and version

psql (PostgreSQL) 17.10 (Debian 17.10-1.pgdg13+1)

Image driver and version

Imagick — ImageMagick 7.1.1-43 Q16 aarch64 22550 https://imagemagick.org

Installed plugins and versions

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions