couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Gonzalez <>
Subject Doing put_attachment + get causes "socket.error: [Errno 104] Connection reset by peer"
Date Fri, 01 Mar 2013 14:57:34 GMT

I am using CouchDB 1.2.0. and couchdb-python 0.9dev.

I will shortly describe my scenario:

   1. I am putting one attachment to a new document (no _rev)
   2. If there is a resource conflict, it means the document was already in
   the database, so I get it, to get the _rev.
   3. I put then the attachment
   4. At some point, you will get a "socket.error: [Errno 104] Connection
   reset by peer". This can either happen in the put_attachment, or in the get

This is the output of my test:

Round 0
Round 1
Round 2
Round 3
Round 4
Round 5
Round 6
Round 7
Round 8
Round 9
Traceback (most recent call last):
  File "", line 30, in <module>
  File "", line 10, in test1
    db.put_attachment(doc, content, 'test-attachment', 'text/plain')
  File "build/bdist.linux-i686/egg/couchdb/", line 673, in
  File "build/bdist.linux-i686/egg/couchdb/", line 460, in put_json
  File "build/bdist.linux-i686/egg/couchdb/", line 439, in put
  File "build/bdist.linux-i686/egg/couchdb/", line 474, in _request
  File "build/bdist.linux-i686/egg/couchdb/", line 334, in request
  File "/usr/local/python/2.7.2/lib/python2.7/", line 548, in read
    s = self._safe_read(self.length)
  File "/usr/local/python/2.7.2/lib/python2.7/", line 647, in
    chunk =, MAXAMOUNT))
  File "/usr/local/python/2.7.2/lib/python2.7/", line 380, in read
    data = self._sock.recv(left)
socket.error: [Errno 104] Connection reset by peer

For this test I have slightly modified the put_attachment method of
couchdb-python, because the stock version does not allow to put an
attachment to a document without a revision, but that operation is valid
for couchdb proper. This is the modified version of put_attachment:

    def put_attachment(self, doc, content, filename=None,
        """Create or replace an attachment.

        Note that the provided `doc` is required to have a ``_rev`` field.
        if the `doc` is based on a view row, the view row would need to
        the ``_rev`` field.

        If the `doc` has no``_rev``, a new document will be created (if

        :param doc: the dictionary or `Document` object representing the
                    document that the attachment should be added to
        :param content: the content to upload, either a file-like object or
                        a string
        :param filename: the name of the attachment file; if omitted, this
                         function tries to get the filename from the
                         object passed as the `content` argument value
        :param content_type: content type of the attachment; if omitted, the
                             MIME type is guessed based on the file name
        :since: 0.4.1
        if filename is None:
            if hasattr(content, 'name'):
                filename = os.path.basename(
                raise ValueError('no filename specified for attachment')
        if content_type is None:
            content_type = ';'.join(
                filter(None, mimetypes.guess_type(filename))

        resource = _doc_resource(self.resource, doc['_id'])
        kwargs = {
            'body' : content,
            'headers' : { 'Content-Type': content_type },
        if '_rev' in doc: kwargs['rev'] = doc['_rev']
        status, headers, data = resource.put_json(filename, **kwargs)
        doc['_rev'] = data['rev']

And this is my test script:

import couchdb

db = couchdb.Server('http://localhost:5984')['unittestdb_deleteme']
doc_id = 'delete-me'

def test1():
    content = "this is the attachment"
    doc = { '_id' : doc_id }
        db.put_attachment(doc, content, 'test-attachment', 'text/plain')
    except couchdb.http.ResourceConflict:
            doc = db[doc_id]
        except Exception, e:
            print type(Exception)
            print e
            db.put_attachment(doc, content, 'test-attachment', 'text/plain')
        except Exception, e:
            print type(Exception)
            print e
        except Exception, e:
            print type(Exception)
            print e

for cnt in xrange(100):
    print "Round %d" % (cnt)

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message