I'm trying to build a covariance-based structural equation model, more precisely a mediation model, using both reflective and formative specifications of latent variables. The purpose of that mediation modal, is to verify if the association between SS and PTGtot is mediated by the mediators STRAP and STRAN (both mediators in the same model).meda, medb, medc and medd are the name of the links. We want to do that by considering SS and PTGtot as reflective constructs and STRAP and STRAN as formative constructs.

enter image description here

my_model <- 
  "PTGtot =~ PTGav + PTGnp + PTGro + PTGps + PTGsc
   SS     =~ SSSres + SSSris
   STRAP <~ SAac + SAv + SApr + SAp + SAh + SAa + SAr
   STRAN <~ SAsd + SAde + SAsu + SAbd + SAsb

   STRAP ~ meda*SS
   PTGtot ~ medb*STRAP
   STRAN ~ medc*SS
   PTGtot ~ medd*STRAN
   PTGtot ~ dir*SS

   indirect1 := meda*medb
   indirect2 := medc*medd
   total := dir+indirect1+indirect2"

model<- lavaan::sem(
  model = my_model,
  data = SIM_final,
  estimator = "MLR",
  missing = "fiml")

When I tried the code above, it gave me no error message. But when I tried to verify my fit indices:

                standardized = TRUE, 
                fit.measures = TRUE, 
                rsquare = TRUE,
                ci = TRUE)

It gives me the following message in output, while providing me my fit indices:

lavaan 0.6-10 did NOT end normally after 2333 iterations
** WARNING ** Estimates below are most likely unreliable

So, based on this post:How to use formative indicators in covariance-based SEM with lavaan? I tried the next code by fixing some parameters and estimating some covariances, arbitrarily:

model<- lavaan::sem(model =

PTGtot~ dir*SS

SS ~~ 1*SS
PTGtot ~~ 1*PTGtot

indirect1 := meda*medb
indirect2 := medc*medd
total := dir+indirect1+indirect2",
                    data = SIM_final,
                    estimator = "MLR",
                    missing = "fiml")

The model is identified, and I don't get any error message when I check my fit indices. But when I try to verify the modification indices:

                   sort. = TRUE)

Its gives me the next message error:

Error in lavaan::modindices(model, sort. = TRUE) : 
  lavaan ERROR: could not compute modification indices; information matrix is singular.

Does anyone knows how to fix the last error message? I specify that none of my variables are perfectly correlated (r=1). I thought that the problem might be the missing values in some data (149 missing values) , but technically full information maximum likelihood estimation is suppose to help to "manage" the missing values (from what I understood).

Furthermore, let me know if anyone see a more intuitive way to write my syntax. This is my first mixed model with formative and reflective constructs, so it is quite possible that there is some things that I wrote something that is not necessary.

There is the code without the mediation part:

model <- ' 
# latent variable definitions
# regression
PTGtot~ dir*SS
# variance
summary(fit <- sem(model, data=SIM_final))

It gives me the next error message:

lavaan 0.6-10 did NOT end normally after 2835 iterations
** WARNING ** Estimates below are most likely unreliable

Thanks in advance.

  • $\begingroup$ I started to tidy your code, to make it easier to read. Do you have a path diagram of the model? It's much easier to think about and explain things if you do. $\endgroup$ Apr 20, 2022 at 21:43
  • $\begingroup$ Also, remove all the mediation stuff for now. Worry about that when the model fits - it makes the model harder to read and understand. $\endgroup$ Apr 20, 2022 at 21:45
  • $\begingroup$ Thank you Jeremy Miles for your advice. I edited my question in order to clarify the situation. In the last code (without mediation). I didn't put anything for variance/covariance because I didn't know what to write. The litterature recommand to "standardize the formatively-measured construct by fixing its variance to unity" and also to "fix the covariance of the disturbance terms to zero". So i guess I need to write someting like: STRAP ~~ 1*STRAP STRAN ~~ 1*STRAN and also STRAP~~0*STRAP STRAN~~0*STRAN ? $\endgroup$ Apr 21, 2022 at 3:07

2 Answers 2


based on this post ...

The post you linked had a critical mistake (and no answers, only comments). Notice that their points 3 and 4 contradict each other about fixing or freeing the composite's variance. I think point 3 was meant to fix the composite's mean, but the syntax they provided was incorrect.

Because you are fixing one formative indicator's effect per composite (STRAP and STRAN) to 1, you should free the composite (residual) variances, which is what your syntax appears to do.

However, you are fixing the first loading of the reflective factors to 1, yet also fixing those factor variances to 1. Only use one of these identification constraints, not both.

Another identification issue is SS only has 2 indicators, which is often problematic unless is has substantially large correlations with another factor. I would recommend fixing both its loadings to 1 to free its variance, which will simply be the observed covariance between those 2 indicators (i.e., their common variance):

SS =~ 1*SSSres + 1*SSSris

That might be related to your convergence problems.

Does anyone knows how to fix the last error message? I specify that none of my variables are perfectly correlated (r=1).

The information matrix is about the estimated parameters, not the variables. If it is singular, then there is probably (multi)collinearity in the estimated joint sampling distribution of your parameter estimates (e.g., when one parameter increase, a combinations of others does to).

Possible solutions

To see whether a pair of parameters is perfectly correlated (the simplest case, not necessarily what you are experiencing), you could look at the standardized, generalized inverse of the information matrix to see whether any correlations are (nearly) 1:

INFO <- lavInspect(fit, "information")
## generalized inverse might work
ACOV <- MASS::ginv(INFO) # usually returned by vcov(fit)
## if so, standardize to correlation matrix
ACOR <- cov2cor(ACOR)
## row/col indices of large correlations
which(abs(ACOR) > .9, arr.ind = TRUE)

But you said you had fit indices. Does that mean your summary() output had SEs for the estimated parameters? If so, then lavaan was able to invert the information matrix in order to calculate the SEs (square-roots of the diagonal of ACOV), so the problem of inversion only happens for the augmented information matrix used to calculate modification indices (which are 1-df score tests).

In that case, I would avoid modindices(), which is overly exploratory anyway. It is likely having trouble adding sensible parameters that make sense in the context of your model, which is complicated by the inclusion of formative constructs/composites. Instead, use the more general score-test function: lavTestScore(). This allows even for multi-parameter score tests (Chou & Bentler, 1990); find lavaan examples in some more recent work (Jorgensen, 2017; Mansolf et al., 2020), as well as the ?lavTestScore help page. But the benefit in your case is that you can think about specific parameters you are actually willing to consider freeing (i.e., because they would make theoretical sense), then specify those in a character string of lavaan syntax to pass to the add= argument. With univariate=TRUE, you get not only the simultaneous score test, but also a 1-df score test (modification index) for each additional parameter you specified. Specifying only a subset might (hopefully) avoid the singular information-matrix issue.

Barring that, I would just look at lavResiduals() to see which pairwise relationships your model fails to reproduce closely, then think about which parameters you could add. That is a good way to choose parameters to pass to lavTestScore() anyway, but if that still fails, you could simply fit less restricted models to get asymptotically equivalent LRT stats (Buse, 1982).


To anyone who is interested in testing signular matrix (or rather for the lavaan library error mentioned in the post) - I prepared a dataset with exactly such data and the code for the model.

Here's dataset

Here's sample model and code

df <- read.csv("singular.csv", sep=';')
model = "f1 =~ q1 + q6\nf2 =~ q2 + q7\nf3 =~ q3 + q8\nf4 =~ q4 + q9\nf5 =~ q5 + q10"
fit <-cfa(model, data=df)
modificationindices(fit, power = TRUE, op = "=~", delta = .4)

And You have modification indices error with singular matrix.

Of course - this is not the only possible case, as this error can be related to many different aspects of the model, or problems not so much with the specification of the model as with the data itself.

However, as there is little evidence for this problem, I have decided to fill this gap. Note that for this data, the model does not de facto find a solution in the short iterative work path (set by default):

> optimizer warns that a solution has NOT been found!

even if You change iterations like this:

fit <-cfa(model, data=df, control=list(iter.max=5000, iter.max=5000))



gives nothing but NA. Anyway - You can test it and learn from it. Good luck. :)


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.