Bom, sei que o tópico é antigo, mas com comentários após 2 anos, presumo que, como eu, muitos irão passar por aqui, lendo sobre erros com transactions.
Não vou postar dúvida, mas, um detalhe importante diante das soluções apresentadas acima (tentar comitar, e se não der, dar um rolback), que até agora testei no Delphi 10.1, Firebird 2.5 e usando Firedac. Coloquei o FDConnection, uma FDQuery, um Datasource. Deixei o FDQuery setado Como padrão, ou seja FetchOptions.RowSetSize 50, e FetchOptions.Mode = fmOnDemand. e Claro, um DBGrid.
Criei uma tabela TAB_TESTE, criei um campo TESTE (varchar 50). Inseri 100 cadastros. No sql da FDQuery, "Select * from tab_teste". Ok, agora vem: ao dar um FDQuery1.active := true, claro, ele irá abrir, trazendo 50 cadastros, e ai vem: deixa a transação aberta (e só fecha ela quando chegar no final da tabela), por exemplo, avançando até o final do DBGrid.
Bom, se logo após o FDQuery1.active = true, eu mandar dar um commit ou rolback na transação, ao tentar rolar o dbgrid até o final.... claro, não vai carregar nenhum cadastro após o 50º.
E é daqui para frente que estou desde sábado último tentando entender porquê "as vezes", o master/detail não salva.
Bem, o código?
...Se não tiver uma transação ativa, iniciar, se já tiver (e tinha) não iniciar, ou pior, comitar, ou dar rolback. Bom, daqui para a frente ví cada erro: parâmetro ftInteger, quando chamados ".AsString", disparando erro. Mas o errão que me fez perder tempo (delphi 10.1 berlim), ao tentar salvar um master/detail (venda e itens da venda), onde há parâmetros nos sql da FDQuery (com a transação lá, aberta, na tabela de fornecedores):
"Firedac -402. operation cannot be performed without assigned selectcommand"
Ainda não testei com zeus, cds, etc.
Bom, colocar FetchOptions.Mode = fmAll "resolve" isto, mas claro, poderá complicar, se houverem muitos cadastros. Iniciar a transação, abrir a tabela e comitar a transação, bom, e o cadastro 51 em diante...