JSON circular reference detected error

In Plone 5.0.4 I have a custom Dexterity content type that has a rich text description field, defined as:

description = RichText(
    title=_(u'Description'),
    description=_(u'This is the description that will be used to promote your program.  Your description should capture the purpose of your program, include an overview of what students will be engaged in while abroad/away, and capture students’ interest! '),
    default_mime_type='text/plain',
    allowed_mime_types=('text/plain', 'text/html',),
    required=False,
)

I've customized the default view for it to display the rich text correctly, but now am finding that in folder_contents view there is a JSON circular reference error, even after I overrode folder_contents to handle the rich text description:

2017-12-26 15:30:58 ERROR Zope.SiteErrorLog 1514323858.480.4250087795 http://localhost:8080/OIE/@@getVocabulary
Traceback (innermost last):
  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module Products.PDBDebugMode.runcall, line 70, in pdb_runcall
  Module ZPublisher.Publish, line 48, in call_object
  Module plone.app.content.browser.vocabulary, line 181, in __call__
  Module plone.app.content.utils, line 16, in json_dumps
  Module json, line 251, in dumps
  Module json.encoder, line 207, in encode
  Module json.encoder, line 270, in iterencode
ValueError: Circular reference detected
> /usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py(270)iterencode()
-> return _iterencode(o, 0)

The offending line is

Is there a way for that vocabulary code not to get the RichTextValue object. (Did you mean <attribute>.raw or <attribute>.output?) return value? I think that's what is giving the JSON parser grief. Other than hacking vocabulary.py to do something like

                 if hasattr(val, 'output'):
                     val = val.output

(which I am not sure I can do without overriding the entire vocabulary.py somehow)

Apparently, the JSON encoder finds a circular structure in items. items is filled with attribute values of vocabulary items. This means, the problem is in some vocabulary and not related to your richtext field.

I would try to identify the vocabulary making the problem (it may be that it is not a vocabulary at all but something else erroneously gotten due to a name clash) and from there see how to fix the problem.

Thanks @dieter – you're right, whether there is any contained item in this folder is irrelevant.

Going up the call stack it seems the offending vocabulary is the portal_catalog (!). Rebuilding the catalog made no difference. I'm going to take a look at a vanilla site to see if it's normal for the catalog to be returned as JSON in folder_contents.

(Pdb) dir(object)
['_BrowserView__getParent', '_BrowserView__setParent', '__ac_permissions__', '__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__implemented__', '__init__', '__module__', '__name__', '__new__', '__of__', '__parent__', '__providedBy__', '__provides__', '__reduce__', '__reduce_ex__', '__repr__', '__roles__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'aq_acquire', 'aq_acquire__roles__', 'aq_base', 'aq_chain', 'aq_inContextOf', 'aq_inContextOf__roles__', 'aq_inner', 'aq_parent', 'aq_self', 'context', 'get_context', 'get_context__roles__', 'get_vocabulary', 'get_vocabulary__roles__', 'parsed_query', 'parsed_query__roles__', 'request']
(Pdb) object.get_vocabulary()
<plone.app.vocabularies.catalog.CatalogVocabulary object at 0x115b94f90>
(Pdb) vocab=object.get_vocabulary()
(Pdb) dir(vocab)
['__class__', '__contains__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',     '__getitem__', '__hash__', '__implemented__', '__init__', '__iter__', '__len__', '__module__', '__new__', '__providedBy__', '__provides__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_brains', '_terms', 'createTerm', 'fromItems',` 'fromValues']
(Pdb) len(vocab)
1
(Pdb) vocab._terms
[<zope.schema.vocabulary.SimpleTerm object at 0x115b94310>]
(Pdb) terms=vocab._terms
(Pdb) terms[0]
<zope.schema.vocabulary.SimpleTerm object at 0x115b94750>
(Pdb) term=terms[0]
(Pdb) dir(term)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__implemented__', '__init__', '__module__', '__new__', '__providedBy__', '__provides__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'title', 'token', 'value']
(Pdb) term.title
'dc99ecf3ec2e456ea029f38c39df7033'
(Pdb) term.value
<Products.ZCatalog.Catalog.mybrains object at 0x11304d738>
(Pdb) term.token
'dc99ecf3ec2e456ea029f38c39df7033'
(Pdb) term.value.absolute_url()
'http://localhost:8080/OIE/portal_catalog'

/Users/kim/PloneBuilds/Plone-5.0.4-unified-clean/buildout-cache/eggs/Zope2-2.13.24-py2.7.egg/ZPublisher/Publish.py(48)call_object()
-> result=apply(object,args) # Type s to step into published object.
(Pdb) args
object = <Products.Five.metaclass.VocabularyView object at 0x116e16490>
args = ()
request =

form

query'{"criteria":[{"i":"UID","o":"plone.app.querystring.operation.list.contains","v":["dc99ecf3ec2e456ea029f38c39df7033"]}]}'
name'plone.app.vocabularies.Catalog'
attributes'["UID","Title","Description","getURL","portal_type","path","ModificationDate","review_state"]'

cookies

_fc_perPage'{"value":"30"}'
castle_session_id'a614aa6f-0441-43ce-9dbf-ffded9485bc5'
_ga'GA1.1.2122322211.1503504551'
welcometour-step'0'
__ac'NjE2NDZkNjk2ZTo2MTY0NmQ2OTZl'
__cp'x%DA%D3%60b%60%60%C8%04b%86hF%20%A1%C1%0A%24J%40%DCbf%20%E1%EF%E9Z%C2%07%A4%0B%F2%8BJ%12s%E2%13%93K2%F3%F3%8A%8B%05%80B%29%F9%C9%A5%B9%A9y%25pAv%A0%60jEIjJf%09%00q%C7%13%EB'

lazy items

SESSION<bound method SessionDataManager.getSessionData of <SessionDataManager at /session_data_manager>>

other

__ac'NjE2NDZkNjk2ZTo2MTY0NmQ2OTZl'
URL0'http://localhost:8080/OIE/@@getVocabulary'
URL2'http://localhost:8080'
query'{"criteria":[{"i":"UID","o":"plone.app.querystring.operation.list.contains","v":["dc99ecf3ec2e456ea029f38c39df7033"]}]}'
attributes'["UID","Title","Description","getURL","portal_type","path","ModificationDate","review_state"]'
AUTHENTICATION_PATH''
LANGUAGE'en-us'
AUTHENTICATED_USER<PropertiedUser 'admin'>
SERVER_URL'http://localhost:8080'
method'GET'
ACTUAL_URL'http://localhost:8080/OIE/@@getVocabulary'
URL'http://localhost:8080/OIE/@@getVocabulary'
PUBLISHED<Products.Five.metaclass.VocabularyView object at 0x116e16490>
name'plone.app.vocabularies.Catalog'
TraversalRequestNameStack
LANGUAGE_TOOL<plone.i18n.utility.LanguageBinding instance at 0x115fc15f0>
BASE0'http://localhost:8080'
BASE1'http://localhost:8080'
BASE2'http://localhost:8080/OIE'
BASE3'http://localhost:8080/OIE/@@getVocabulary'
URL1'http://localhost:8080/OIE'
URL0http://localhost:8080/OIE/@@getVocabulary
URL1http://localhost:8080/OIE
URL2http://localhost:8080
BASE0http://localhost:8080
BASE1http://localhost:8080
BASE2http://localhost:8080/OIE
BASE3http://localhost:8080/OIE/@@getVocabulary

environ

HTTP_COOKIE'_fc_perPage=%7B%22value%22%3A%2230%22%7D; castle_session_id="a614aa6f-0441-43ce-9dbf-ffded9485bc5"; welcometour-step=0; _ga=GA1.1.2122322211.1503504551; __ac="NjE2NDZkNjk2ZTo2MTY0NmQ2OTZl"; __cp="x%25DA%25D3%2560b%2560%2560%25C8%2504b%2586hF%2520%25A1%25C1%250A%2524J%2540%25DCbf%2520%25E1%25EF%25E9Z%25C2%2507%25A4%250B%25F2%258BJ%2512s%25E2%2513%2593K2%25F3%25F3%258A%258B%2505%2580B%2529%25F9%25C9%25A5%25B9%25A9y%2525pAv%25A0%2560jEIjJf%2509%2500q%25C7%2513%25EB"'
SERVER_SOFTWARE'Zope/(2.13.24, python 2.7.14, darwin) ZServer/1.1'
SCRIPT_NAME''
REQUEST_METHOD'GET'
PATH_INFO'/OIE/@@getVocabulary'
SERVER_PROTOCOL'HTTP/1.1'
QUERY_STRING'name=plone.app.vocabularies.Catalog&query=%7B%22criteria%22%3A%5B%7B%22i%22%3A%22UID%22%2C%22o%22%3A%22plone.app.querystring.operation.list.contains%22%2C%22v%22%3A%5B%22dc99ecf3ec2e456ea029f38c39df7033%22%5D%7D%5D%7D&attributes=%5B%22UID%22%2C%22Title%22%2C%22Description%22%2C%22getURL%22%2C%22portal_type%22%2C%22path%22%2C%22ModificationDate%22%2C%22review_state%22%5D'
channel.creation_time1515518705
CONNECTION_TYPE'keep-alive'
HTTP_USER_AGENT'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'
HTTP_REFERER'http://localhost:8080/OIE/programs/a-new-study-away-program/folder_contents'
SERVER_NAME'TKNMBP2-3.local'
REMOTE_ADDR'127.0.0.1'
PATH_TRANSLATED'/OIE/@@getVocabulary'
SERVER_PORT'8080'
HTTP_X_REQUESTED_WITH'XMLHttpRequest'
HTTP_DNT'1'
HTTP_HOST'localhost:8080'
HTTP_ACCEPT'application/json, text/javascript, /; q=0.01'
GATEWAY_INTERFACE'CGI/1.1'
HTTP_ACCEPT_LANGUAGE'en-US,en;q=0.9'
HTTP_X_THEME_ENABLEDTrue
HTTP_ACCEPT_ENCODING'gzip, deflate, br'

Hello,

Sorry to "necropost" but I'll add my two cents here in case someone else had/have the same issue.

We came across almost the same problem in our Plone 5.2 site ("ValueError: Circular reference detected" on folder_contents view).

We had a RichText field in a custom Dexterity content type that had a metadata column in the portal_catalog. The problem occured because the field had no proper indexer and the RichTextValue object was stocked per se "as is" in the metadata column.

So the solution was to simply add an indexer like this for the RichText field :

@indexer(IMyCustomContentType)
def get_my_rich_text_field_output(object):
    return object.my_rich_text_field.output

then register it like this:
<adapter name="my_rich_text_field" factory=".custom_content_type.get_my_rich_text_field_output" />

finally in catalog.xml:
<column value="my_rich_text_field" />

After that, it worked like a charm.

2 Likes

Thank you! Much cleaner than the solution I came up with.

1 Like