I'm working on a plugin in Craft 3 that is fetching a file reference (URL) via an API.

I want to fetch the file and save it locally as an Asset. I've tried to do this via Craft::$app->getElements()->saveElement() but am getting the following error:

New Location cannot be blank.

Any thoughts on this issue or where to dig a bit deeper to resolve?


2 Answers 2


Not an answer directly to your question but a general function to upload an asset in PHP. In my case $file is an uploaded file in the $_FILES array. You can download a file per url and insert it's tmp_name and name manually

 * Upload a file
 * @param $file
 * @return int|null|string
 * @throws \Throwable
 * @throws \craft\errors\ElementNotFoundException
 * @throws \yii\base\Exception
public function uploadImage($file)
    $assets = Craft::$app->getAssets();
    $folderId = 1; //<- insert your folder id

    /** @var \craft\models\VolumeFolder $folder */
    $folder = $assets->findFolder(['id' => $folderId]);

    $asset = new Asset();
    $asset->tempFilePath = $file['tmp_name'];
    $asset->filename = $file['name'];
    $asset->newFolderId = $folder->id;
    $asset->volumeId = $folder->volumeId;
    $asset->avoidFilenameConflicts = true;

    $result = Craft::$app->getElements()->saveElement($asset);

    // In case of error, let user know about it.
    if ($result === false) {
        throw new Exception('Error while upload asset');

    return $asset->id;

I ran into this problem too, and isolated it to AssetLocationValidator.php on line 110 or so.

// If nothing has changed, just null-out the newLocation attribute
if (!$hasNewFolderId && !$hasNewFilename) {
    $model->$attribute = null;


but the problem is, having a null newLocation throws a validation error.

My solution was to set the folderId as 0, and the newFolderId as the destination folder. This keeps the "null out the newLocation..." from firing, and keeps the newLocation populated.

$asset = new Asset();
$asset->tempFilePath = $tempPath;
$asset->filename = $filename;
$asset->folderId = 0;
$asset->newFolderId = $folder->id;
$asset->volumeId = $folder->volumeId;
$asset->avoidFilenameConflicts = true;

$result = Craft::$app->getElements()->saveElement($asset);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.