Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

boneill81's avatar

Serious issue where Save() returns true but record is not persisted to the database

Hi All, I have come across and tested a serious issue where save() returns true but does not persist the record to the database. I had some questions on this.

The error in question happened because a new field added to the data model had erroneously not been assigned a default value.

However with this in mind, the expected behaviour of the save() method would be to return false in this case. But it returned true. The same behaviour was observered using firstOrCreate() and firstOrNew() also which in I realise are essentially just convenience wrappers for save() so it makes sense that they returned the same value.

I see this as an extremely serious error. This was being run within a transaction. Had it not been for me subsequently trying to attach some relations to the created model, then no exception would have been thrown and the transaction would have committed and returned true while it had silently failed.

 DB::beginTransaction();
    try{
        $taxonRecord = new TaxonRecord($attributes);
        $recordSource = $taxonRecord->recordSource;
        $taxonRecord->record_source_name = $recordSource->name;
        DB::enableQueryLog();
        if(!$taxonRecord->save()){//I specifically put in this if statement to try and make it catch the error but it still does not
            Log::error($taxonRecord);
            throw new \Exception('Taxon record was not saved.');
        }
        Log::info(DB::getQueryLog());//Query log shows the query and bindings. When run in heidiSql I discovered the miss


        //This fails since there is now an integrity constraint since the TaxonRecord was not actually perisited. We should not have reached this point!!
        $customAttributes = $recordSource->customAttributes;
        foreach($customAttributes as $customAttribute){
            $customAttributeValue = array_get($attributes, $customAttribute->name, null);//Find the attribute in the array, set to null if it does not exist.
            if( !empty($customAttributeValue) ){
                $taxonRecord->customAttributes()->attach([ $customAttribute->custom_attribute_id => ['value' => $customAttributeValue] ]);
            }
        }
        DB::commit();
        return $taxonRecord;
    } catch (\Exception $e){
        DB::rollBack();
        Log::error($e);
        return false;
    }

Your thought's please gentlemen.

0 likes
3 replies
Snapey's avatar

whether an error is thrown depends on the version of the database. Not supplying field data and creating a record is fine without strict mode

boneill81's avatar

I know what you mean but in this case MariaDB did actually throw an error but Laravel seems to have ignored it and carried on. It seems odd to me. Perhaps I am missing something? I ran the raw output from the query log and it immediately fired the error.

boneill81's avatar
boneill81
OP
Best Answer
Level 1

I got to the bottom of this today. This was a bug with MariaDB which has been fixed in 10.1.22. See here for details https://jira.mariadb.org/browse/MDEV-11842.

Basically HeidiSQL could see that the row had not been added and threw its own error but MariaDB did not throw an actual error which is why save() could not ascertain that anything was amiss. Hopefully it will help someone else.

Thanks.

Please or to participate in this conversation.